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..76932ae97 --- /dev/null +++ b/assets/js/dialog.js @@ -0,0 +1,63 @@ +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 openDialogOnHash() { + const hash = window.location.hash; + if (!hash) return; + + const targetId = decodeURIComponent(hash.substring(1)); + const targetElement = document.getElementById(targetId); + + if (targetElement) { + const dialog = targetElement.closest("dialog"); + if (dialog && !dialog.open) { + 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); + }); + + // Initialize hash check + openDialogOnHash(); + window.addEventListener("hashchange", openDialogOnHash); +} + +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/content/operator/stl/index.de.md b/content/operator/stl/index.de.md index 88a1afb07..fe2984514 100644 --- a/content/operator/stl/index.de.md +++ b/content/operator/stl/index.de.md @@ -186,4 +186,40 @@ Stena Line bietet eine tolle Möglichkeit, um vor 10 Uhr in London zu sein, wenn [^3]: [Website Stena Line](https://www.stenaline.de/routen/hoek-van-holland-harwich) -[^4]: [E-Mail-Anfrage des FIP Guide Teams bei Stena Line](https://github.com/fipguide/fipguide.github.io/issues/528) +[^4]: [E-Mail-Anfrage des FIP Guide Teams bei Stena Line](dialog:stena-line-email) + +{{% dialog + id="stena-line-email" + title="E-Mail-Anfrage des FIP Guide Teams bei Stena Line" +%}} + +# RE: Vielen Dank für Ihre E-Mail - CASE:172468 + +**Von:** Stena Line UK contact.uk.info@stenaline.com \ +**An:** Robert Schuster nextstop@fipguide.org \ +**Datum:** Mo. 1. Dez. 2025, 10:59 + +Hello, + +Thank you for contacting us. + +Concessions bookings can be made by phone or on the day of travel, subject to availability. + +The cost of the booking depends on the type of concessions pass you hold. Generally, the overnight sailing is more expensive than the daytime crossing, as the fare for the overnight journey is higher and cabins are mandatory. + +The concessions fare only provides a discount on the fare price; any additional extras are charged at full price and are not discounted. + +For more information or a travel quote, please contact [03447 7070 70](tel:03447707070), and a member of our team will be glad to assist you. + +Thank you + +Best regards + +Stacey + +Contact Centre agent + +Call: [03447 707070](tel:03447707070) (UK) [+353 1871 4711](tel:+35318714711) (IRL) + +Internet: www.stenaline.co.uk +{{% /dialog %}} diff --git a/content/operator/stl/index.en.md b/content/operator/stl/index.en.md index ef17a4b99..173a5d0d8 100644 --- a/content/operator/stl/index.en.md +++ b/content/operator/stl/index.en.md @@ -186,4 +186,40 @@ Stena Line offers a great way to be in London before 10 am if you invest a littl [^3]: [Stena Line Website](https://www.stenaline.de/routen/hoek-van-holland-harwich) -[^4]: [FIP Guide Team email inquiry to Stena Line](https://github.com/fipguide/fipguide.github.io/issues/528) +[^4]: [FIP Guide Team email inquiry to Stena Line](dialog:stena-line-email) + +{{% dialog + id="stena-line-email" + title="FIP Guide Team email inquiry to Stena Line" +%}} + +# RE: Vielen Dank für Ihre E-Mail - CASE:172468 + +**From:** Stena Line UK contact.uk.info@stenaline.com \ +**To:** Robert Schuster nextstop@fipguide.org \ +**Date:** Mon, 1 Dec 2025, 10:59 + +Hello, + +Thank you for contacting us. + +Concessions bookings can be made by phone or on the day of travel, subject to availability. + +The cost of the booking depends on the type of concessions pass you hold. Generally, the overnight sailing is more expensive than the daytime crossing, as the fare for the overnight journey is higher and cabins are mandatory. + +The concessions fare only provides a discount on the fare price; any additional extras are charged at full price and are not discounted. + +For more information or a travel quote, please contact [03447 7070 70](tel:03447707070), and a member of our team will be glad to assist you. + +Thank you + +Best regards + +Stacey + +Contact Centre agent + +Call: [03447 707070](tel:03447707070) (UK) [+353 1871 4711](tel:+35318714711) (IRL) + +Internet: www.stenaline.co.uk +{{% /dialog %}} diff --git a/content/operator/stl/index.fr.md b/content/operator/stl/index.fr.md index 27e0e5ef4..4259b35de 100644 --- a/content/operator/stl/index.fr.md +++ b/content/operator/stl/index.fr.md @@ -184,4 +184,40 @@ Stena Line offre une excellente possibilité d’arriver à Londres avant 10h si [^3]: [Site Web Stena Line](https://www.stenaline.de/routen/hoek-van-holland-harwich) -[^4]: [Demande par e-mail de l’équipe FIP Guide à Stena Line](https://github.com/fipguide/fipguide.github.io/issues/528) +[^4]: [Demande par e-mail de l’équipe FIP Guide à Stena Line](dialog:stena-line-email) + +{{% dialog + id="stena-line-email" + title="Demande par e-mail de l’équipe FIP Guide à Stena Line" +%}} + +# RE: Vielen Dank für Ihre E-Mail - CASE:172468 + +**De :** Stena Line UK contact.uk.info@stenaline.com \ +**À :** Robert Schuster nextstop@fipguide.org \ +**Date :** lun. 1 déc. 2025, 10:59 + +Hello, + +Thank you for contacting us. + +Concessions bookings can be made by phone or on the day of travel, subject to availability. + +The cost of the booking depends on the type of concessions pass you hold. Generally, the overnight sailing is more expensive than the daytime crossing, as the fare for the overnight journey is higher and cabins are mandatory. + +The concessions fare only provides a discount on the fare price; any additional extras are charged at full price and are not discounted. + +For more information or a travel quote, please contact [03447 7070 70](tel:03447707070), and a member of our team will be glad to assist you. + +Thank you + +Best regards + +Stacey + +Contact Centre agent + +Call: [03447 707070](tel:03447707070) (UK) [+353 1871 4711](tel:+35318714711) (IRL) + +Internet: www.stenaline.co.uk +{{% /dialog %}} 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 }} + + {{- .Text -}} + +{{ 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`) */ -}}