Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions assets/js/contentNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -107,10 +109,9 @@ const initAside = () => {
wasMobile = true;
closeSheet();
}
if (!isMobile()) {
if (wasMobile && !isMobile()) {
wasMobile = false;
closeOverlay();
aside.classList.remove("o-aside--open");
closeSheet();
}
};

Expand Down
68 changes: 68 additions & 0 deletions assets/js/dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {
openOverlay,
closeOverlay,
addOverlayClickListener,
} from "./overlay.js";

function getCloseButton(dialog) {
return dialog.querySelector(".o-dialog__header > .a-button");
}

function openDialog(dialogId) {
const dialog = document.getElementById(dialogId);
if (!dialog) return;

dialog.show();
openOverlay("dialog");

const closeButton = getCloseButton(dialog);
if (closeButton) {
closeButton.addEventListener("click", () => closeDialog(dialog));
}
}

function closeDialog(dialog) {
const closeButton = getCloseButton(dialog);
if (closeButton) {
closeButton.replaceWith(closeButton.cloneNode(true));
}
dialog.close();
closeOverlay();
}

function closeAllDialogs() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could there be more than one open dialog? do you think of a dialog in a dialog? 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say that we shouldn't do that. And if we do so, we can still update the implementation, but it makes it a bit more complex if we need to track which dialog is the one with the highest z-index.

document.querySelectorAll("dialog[open]").forEach((dialog) => {
closeDialog(dialog);
});
}

function initDialogs() {
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);
});

addOverlayClickListener(() => {
closeAllDialogs();
});

document.addEventListener("keydown", (e) => {
if (e.key === "Escape") {
closeAllDialogs();
}
});
}

if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initDialogs);
} else {
initDialogs();
}
1 change: 1 addition & 0 deletions assets/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ import "./dropdown.js";
import "./search.js";
import "./interactiveMap.js";
import "./expander.js";
import "./dialog.js";
2 changes: 2 additions & 0 deletions assets/js/mobileMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 8 additions & 1 deletion assets/sass/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,4 +24,12 @@
padding: 0.6rem;
display: block;
}

&__external {
border: 0.2rem solid var(--link-default);
}

&__internal {
border: none;
}
}
67 changes: 67 additions & 0 deletions assets/sass/dialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.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;
position: fixed;
top: 7rem;
border: none;
padding: 0;
background-color: var(--bg-default);
color: var(--color-body);
border-radius: var(--border-radius-m);
z-index: 12;
border: var(--border);
overflow: hidden;
}

&__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;
}
}
}
5 changes: 5 additions & 0 deletions assets/sass/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@
z-index: 14;
}

#header:has(.overlay--dialog),
.overlay--dialog {
z-index: 10;
}

body:has(.overlay--show) {
overflow: hidden;
}
1 change: 1 addition & 0 deletions assets/sass/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@
@import "tag.scss";
@import "floatImage.scss";
@import "teamMember.scss";
@import "dialog.scss";
9 changes: 8 additions & 1 deletion assets/sass/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -80,6 +83,10 @@ a {
display: none;
}
}

& > .material-symbols-rounded {
margin: 0 0.2rem;
}
}

main {
Expand Down
2 changes: 1 addition & 1 deletion content/country/belgium/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
3 changes: 3 additions & 0 deletions i18n/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions i18n/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions i18n/fr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion layouts/partials/booking.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 -}}
</div>

Expand Down
25 changes: 17 additions & 8 deletions layouts/partials/button.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
<a
href="{{ .Destination }}"
target="_blank"
rel="noopener noreferrer"
class="a-button o-link__external"
>
{{- .Text -}}{{- partial "icon" "arrow_outward" -}}
</a>
{{ if .Destination }}
<a
href="{{ .Destination }}"
target="_blank"
rel="noopener noreferrer"
class="a-button a-button__external o-link__external"
>
{{- .Text -}}{{- partial "icon" "arrow_outward" -}}
</a>
{{ else }}
<button
class="a-button a-button__internal"
{{- with .Title }}title="{{ . }}"{{- end -}}
>
{{- .Text -}}
</button>
{{ end }}
15 changes: 15 additions & 0 deletions layouts/partials/dialog.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<dialog
Copy link
Member

@therobrob therobrob Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i’m wondering, why the dialog is modal: false in MS Edge. A bug?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially used the modal dialog implementation, opened via openModal(). Modal dialogs add a top-layer to the DOM and closing the dialog by click on the overlay doesn't work anymore (all interaction outside the dialog is blocked):

The showModal() method of the HTMLDialogElement interface displays the dialog as a modal, over the top of any other dialogs that might be present. It displays into the top layer, along with a ::backdrop pseudo-element. Interaction outside the dialog is blocked and the content outside it is rendered inert.

There is a workaround, described here: https://stackoverflow.com/a/73988585. But it's not pretty and we wouldn't be able to use our overlay.

So I went for a normal dialog with out own overlay, but then modal is not set. Maybe we can tune it manually via some attributes. Where do you see the modal setting in Edge?

id="{{ .ID }}"
class="o-dialog__wrapper"
aria-labelledby="{{ .ID }}-title"
>
<div class="o-dialog o-container">
<header class="o-dialog__header">
<h1 id="{{ .ID }}-title" class="o-dialog__title">{{ .Title }}</h1>
{{- partial "button" (dict "Text" (partial "icon" "close") "Title" (i18n "dialog.close")) -}}
</header>
<div class="o-dialog__body">
{{- partial "increase-headings" (dict "content" .Content) | safeHTML -}}
</div>
</div>
</dialog>
22 changes: 17 additions & 5 deletions layouts/partials/link.html
Original file line number Diff line number Diff line change
@@ -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` */ -}}
<a
href="{{ .Destination }}"
target="_blank"
Expand All @@ -11,8 +11,20 @@
>
{{- .Text -}}{{- partial "icon" "arrow_outward" -}}
</a>
{{- else if strings.HasPrefix $url "dialog:" -}}
{{- /* Dialog triggers, e.g. `dialog:test` */ -}}
<span
class="o-link"
role="button"
tabindex="0"
aria-haspopup="dialog"
aria-label="{{ T "dialog.open" }}"
data-dialog-trigger="{{ strings.TrimPrefix "dialog:" $url }}"
>
{{- .Text -}}{{- partial "icon" "open_in_browser" -}}
</span>
{{- else if strings.HasPrefix $url "mailto:" -}}
{{- /* Email links, e. g. `mailto:example@example.com` */ -}}
{{- /* Email links, e.g. `mailto:example@example.com` */ -}}
<a
href="{{ $url }}"
class="o-link__mail"
Expand All @@ -21,7 +33,7 @@
{{- partial "icon" "mail" -}}{{- .Text -}}
</a>
{{- else if strings.HasPrefix $url "tel:" -}}
{{- /* Telephone links, e. g. `tel:+1234567890` */ -}}
{{- /* Telephone links, e.g. `tel:+1234567890` */ -}}
<a
href="{{ $url | safeURL }}"
class="o-link__tel"
Expand All @@ -30,15 +42,15 @@
{{- partial "icon" "call" -}}{{- .Text -}}
</a>
{{- 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`) */ -}}
<a
href="{{ .Page.Ref (dict "path" $url) }}"
{{- with .Title -}}title="{{ . }}"{{- end -}}
>
{{- .Text -}}
</a>
{{- 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`) */ -}}
<a
href="{{ $url | relURL }}"
{{- with .Title -}}title="{{ . }}"{{- end -}}
Expand Down
1 change: 0 additions & 1 deletion layouts/partials/remove-newlines.html

This file was deleted.

Loading
Loading