diff --git a/assets/js/contentNavigation.js b/assets/js/contentNavigation.js index b61e21edd..8da2a51db 100644 --- a/assets/js/contentNavigation.js +++ b/assets/js/contentNavigation.js @@ -19,6 +19,8 @@ const initAside = () => { let isClosed = true; const closeSheet = () => { + if (isClosed) return; + isClosed = true; aside.classList.remove("o-aside--open"); asideContent.removeAttribute("role"); @@ -107,10 +109,9 @@ const initAside = () => { wasMobile = true; closeSheet(); } - if (!isMobile()) { + if (wasMobile && !isMobile()) { wasMobile = false; - closeOverlay(); - aside.classList.remove("o-aside--open"); + closeSheet(); } }; diff --git a/assets/js/dialog.js b/assets/js/dialog.js new file mode 100644 index 000000000..711e2b900 --- /dev/null +++ b/assets/js/dialog.js @@ -0,0 +1,44 @@ +function getCloseButton(dialog) { + return dialog.querySelector(".o-dialog__header > .a-button"); +} + +function openDialog(dialogId) { + const dialog = document.getElementById(dialogId); + if (!dialog) return; + + dialog.showModal(); +} + +function initDialogs() { + document.querySelectorAll("dialog").forEach((dialog) => { + dialog.addEventListener("click", (e) => { + if (e.target === dialog) { + dialog.close(); + } + }); + + const closeButton = getCloseButton(dialog); + if (closeButton) { + closeButton.addEventListener("click", () => dialog.close()); + } + }); + + document.querySelectorAll("[data-dialog-trigger]").forEach((trigger) => { + const handler = (e) => { + if (e.type === "click" || (e.type === "keydown" && e.key === "Enter")) { + e.preventDefault(); + const dialogId = trigger.getAttribute("data-dialog-trigger"); + openDialog(dialogId); + } + }; + + trigger.addEventListener("click", handler); + trigger.addEventListener("keydown", handler); + }); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", initDialogs); +} else { + initDialogs(); +} diff --git a/assets/js/main.js b/assets/js/main.js index 964b1f435..830c8a4e9 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -9,3 +9,4 @@ import "./dropdown.js"; import "./search.js"; import "./interactiveMap.js"; import "./expander.js"; +import "./dialog.js"; diff --git a/assets/js/mobileMenu.js b/assets/js/mobileMenu.js index 7190d65f7..4ffe0c095 100644 --- a/assets/js/mobileMenu.js +++ b/assets/js/mobileMenu.js @@ -39,6 +39,8 @@ function closeMobileMenu() { const navContainer = document.querySelector(".o-header__nav"); const menuButton = document.querySelector(".o-nav__menu-button"); + if (!navContainer.classList.contains("o-header__nav--open")) return; + navContainer.classList.remove("o-header__nav--open"); menuButton.setAttribute("aria-expanded", false); closeOverlay(); diff --git a/assets/sass/button.scss b/assets/sass/button.scss index 7d6b7a82a..a8b94a33f 100644 --- a/assets/sass/button.scss +++ b/assets/sass/button.scss @@ -3,7 +3,6 @@ display: inline-flex; align-items: center; gap: 0.4rem; - border: 0.2rem solid var(--link-default); border-radius: var(--border-radius-m); font-size: 1.5rem; cursor: pointer; @@ -25,4 +24,12 @@ padding: 0.6rem; display: block; } + + &__external { + border: 0.2rem solid var(--link-default); + } + + &__internal { + border: none; + } } diff --git a/assets/sass/dialog.scss b/assets/sass/dialog.scss new file mode 100644 index 000000000..a31c389c1 --- /dev/null +++ b/assets/sass/dialog.scss @@ -0,0 +1,69 @@ +.o-dialog { + max-height: calc(100dvh - 14rem); + overflow: auto; + display: flex; + flex-direction: column; + + .a-anchorlink { + margin-bottom: 0; + + &__link { + display: none; + } + + > h2 { + margin-bottom: 1rem; + } + } + + .o-divider { + display: none; + } + + &__wrapper { + width: fit-content; + border: none; + padding: 0; + background-color: var(--bg-default); + color: var(--color-body); + border-radius: var(--border-radius-m); + border: var(--border); + overflow: hidden; + + &::backdrop { + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); + } + } + + &__header { + position: sticky; + top: 0; + background-color: var(--bg-default); + display: flex; + column-gap: 1rem; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem 1rem 2rem; + border-bottom: var(--border); + border-color: var(--color-table-border); + + .o-divider { + display: none; + } + + > h1 { + margin: 0; + font-size: 2.2rem; + } + } + + &__body { + padding: 2rem; + overflow: auto; + + > *:last-child { + margin-bottom: 0; + } + } +} diff --git a/assets/sass/header.scss b/assets/sass/header.scss index 12ab32738..cfeba756d 100644 --- a/assets/sass/header.scss +++ b/assets/sass/header.scss @@ -102,6 +102,12 @@ z-index: 14; } -body:has(.overlay--show) { +#header:has(.overlay--dialog), +.overlay--dialog { + z-index: 10; +} + +body:has(.overlay--show), +body:has(dialog[open]) { overflow: hidden; } diff --git a/assets/sass/main.scss b/assets/sass/main.scss index 45cbf8c95..eb8db79af 100644 --- a/assets/sass/main.scss +++ b/assets/sass/main.scss @@ -23,3 +23,4 @@ @import "tag.scss"; @import "floatImage.scss"; @import "teamMember.scss"; +@import "dialog.scss"; diff --git a/assets/sass/styles.scss b/assets/sass/styles.scss index 53da76e6e..e87f1b5e1 100644 --- a/assets/sass/styles.scss +++ b/assets/sass/styles.scss @@ -57,13 +57,16 @@ button { @include focus-indicator(0.2rem); } -a { +a, +.o-link { color: var(--link-default); transition: color 0.3s ease, background-color 0.3s ease; text-underline-offset: 0.2rem; border-radius: var(--border-radius-s); + text-decoration: underline; + cursor: pointer; &:hover, &:focus { @@ -80,6 +83,10 @@ a { display: none; } } + + & > .material-symbols-rounded { + margin: 0 0.2rem; + } } main { diff --git a/content/country/belgium/index.en.md b/content/country/belgium/index.en.md index c53314908..66a531fd0 100644 --- a/content/country/belgium/index.en.md +++ b/content/country/belgium/index.en.md @@ -17,7 +17,7 @@ Additionally, international [Eurostar](/operator/eurostar "Eurostar") trains ope Furthermore, international `TGV` trains of the [SNCF](/operator/sncf "SNCF") from France operate, for which the FIP Coupon of SNCB are not valid. Only special FIP Global Fares can be booked for these trains. For the Eurocity trains from Brussels to Paris operated by OUIGO, no FIP discounts apply. {{< identify-operator sources="db-website,vagonweb" >}} -Not all trains in the country (e. g. `ICE`) are shown in the [SNCB / NMBS online timetable](https://www.belgiantrain.be/en/). +Not all trains in the country (e.g. `ICE`) are shown in the [SNCB / NMBS online timetable](https://www.belgiantrain.be/en/). {{< /identify-operator >}} ## Interesting diff --git a/content/identify-operator/renfe-commuter-website/index.en.md b/content/identify-operator/renfe-commuter-website/index.en.md index da086cc40..deb301449 100644 --- a/content/identify-operator/renfe-commuter-website/index.en.md +++ b/content/identify-operator/renfe-commuter-website/index.en.md @@ -4,4 +4,4 @@ params: url: "https://www.renfe.com/es/en/suburban" --- -On the Renfe Cercanías website (suburban trains), you can search for train connections in any suburban train network. To do this, select the relevant region on the website and then click on _Timetables_. In suburban train networks with multiple operators (e. g. Barcelona), only Renfe trains are displayed. +On the Renfe Cercanías website (suburban trains), you can search for train connections in any suburban train network. To do this, select the relevant region on the website and then click on _Timetables_. In suburban train networks with multiple operators (e.g. Barcelona), only Renfe trains are displayed. diff --git a/i18n/de.yaml b/i18n/de.yaml index a2361e110..165bf5ea8 100644 --- a/i18n/de.yaml +++ b/i18n/de.yaml @@ -39,6 +39,9 @@ country: many: Länder one: Land other: Länder +dialog: + close: Schließen + open: Öffnet Dialog discord: FIP Guide Community donation: Spenden editPage: Seite bearbeiten diff --git a/i18n/en.yaml b/i18n/en.yaml index 0064abeaa..a05a25108 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -38,6 +38,9 @@ country: many: countries one: country other: countries +dialog: + close: Close + open: Opens dialog discord: FIP Guide Community donation: Donate editPage: Edit page diff --git a/i18n/fr.yaml b/i18n/fr.yaml index e7d456734..12c0d7526 100644 --- a/i18n/fr.yaml +++ b/i18n/fr.yaml @@ -39,6 +39,9 @@ country: one: pays other: pays countryselection: Choisir un pays +dialog: + close: Fermer + open: Ouvre le dialogue discord: Communauté FIP Guide donation: Donation editPage: Modifier la page diff --git a/layouts/partials/booking.html b/layouts/partials/booking.html index d28991f0e..e59b51390 100644 --- a/layouts/partials/booking.html +++ b/layouts/partials/booking.html @@ -85,7 +85,6 @@ {{- $content := partial "increase-headings" (dict "content" .page.Content "offset" 2) -}} {{- $content := partial "prefix-footnotes" (dict "content" $content "prefix" .page.File.ContentBaseName) -}} {{- $content := partial "prefix-heading-ids" (dict "content" $content "prefix" .page.File.ContentBaseName) -}} - {{- $content := partial "remove-newlines" $content -}} {{- $content | safeHTML -}} diff --git a/layouts/partials/button.html b/layouts/partials/button.html index 647ca8d73..0c7819991 100644 --- a/layouts/partials/button.html +++ b/layouts/partials/button.html @@ -1,8 +1,17 @@ - - {{- .Text -}}{{- partial "icon" "arrow_outward" -}} - +{{ if .Destination }} + + {{- .Text -}}{{- partial "icon" "arrow_outward" -}} + +{{ else }} + +{{ end }} diff --git a/layouts/partials/dialog.html b/layouts/partials/dialog.html new file mode 100644 index 000000000..2ad259d59 --- /dev/null +++ b/layouts/partials/dialog.html @@ -0,0 +1,15 @@ + +
+
+

{{ .Title }}

+ {{- partial "button" (dict "Text" (partial "icon" "close") "Title" (i18n "dialog.close")) -}} +
+
+ {{- partial "increase-headings" (dict "content" .Content) | safeHTML -}} +
+
+
diff --git a/layouts/partials/link.html b/layouts/partials/link.html index 841a93abe..767e9f317 100644 --- a/layouts/partials/link.html +++ b/layouts/partials/link.html @@ -1,6 +1,6 @@ {{- $url := .Destination -}} {{- if and (strings.HasPrefix $url "http") (not (strings.HasPrefix $url site.BaseURL)) -}} - {{- /* Absolute links pointing to external pages, e. g. `https://example.com` */ -}} + {{- /* Absolute links pointing to external pages, e.g. `https://example.com` */ -}} {{- .Text -}}{{- partial "icon" "arrow_outward" -}} +{{- else if strings.HasPrefix $url "dialog:" -}} + {{- /* Dialog triggers, e.g. `dialog:test` */ -}} + + {{- .Text -}}{{- partial "icon" "open_in_browser" -}} + {{- else if strings.HasPrefix $url "mailto:" -}} - {{- /* Email links, e. g. `mailto:example@example.com` */ -}} + {{- /* Email links, e.g. `mailto:example@example.com` */ -}} {{- else if strings.HasPrefix $url "tel:" -}} - {{- /* Telephone links, e. g. `tel:+1234567890` */ -}} + {{- /* Telephone links, e.g. `tel:+1234567890` */ -}} {{- else if .Page.Ref (dict "path" $url) -}} - {{- /* Internal links, referenced by path (e. g. `/news/1`) */ -}} + {{- /* Internal links, referenced by path (e.g. `/news/1`) */ -}} {{- else if or (strings.HasPrefix $url "/") (strings.HasPrefix $url site.BaseURL) -}} - {{- /* Internal links, referenced by URL (e. g. `/en/news/1`) */ -}} + {{- /* Internal links, referenced by URL (e.g. `/en/news/1`) */ -}}