Skip to content

Commit 923f938

Browse files
feat: Add support for dialogs (#680)
Dialogs are a helpful element for presenting content without cluttering the main page. They are basis for the implementation of #446 and #558. A dialog usually consists of two parts: The trigger and the dialog content. If you want to use dialogs in the Markdown content, we provide two helpers for dialog creation and linking. To add the dialog content, add the following shortcode to the respective page content: ```md {{% dialog id="test" title="Test" %}} This is the content of the dialog. {{% /dialog %}} ``` **IMPORTANT:** The dialog id must be unique on the relevant page. As you'll notice, there is no change to the page. We have to create a trigger. The easiest way is link-based trigger. You can reference the dialog by ID: ``` [This is the trigger for the dialog](dialog:test) ``` For better visualization, I added the "[FIP Guide Team email inquiry to Stena Line](https://deploy-preview-680--fipguide.netlify.app/de/operator/stl/#quellen)" source as dialog. TODO: - [x] z-index of overlay has to be increased to cover the header - [x] For better contrast add border to dialog - [x] New lines for email header - [x] Button alignment on mobile --------- Co-authored-by: Robert Schuster <77234379+therobrob@users.noreply.github.com>
1 parent d41f453 commit 923f938

20 files changed

Lines changed: 229 additions & 23 deletions

File tree

assets/js/contentNavigation.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const initAside = () => {
1919
let isClosed = true;
2020

2121
const closeSheet = () => {
22+
if (isClosed) return;
23+
2224
isClosed = true;
2325
aside.classList.remove("o-aside--open");
2426
asideContent.removeAttribute("role");
@@ -107,10 +109,9 @@ const initAside = () => {
107109
wasMobile = true;
108110
closeSheet();
109111
}
110-
if (!isMobile()) {
112+
if (wasMobile && !isMobile()) {
111113
wasMobile = false;
112-
closeOverlay();
113-
aside.classList.remove("o-aside--open");
114+
closeSheet();
114115
}
115116
};
116117

assets/js/dialog.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
function getCloseButton(dialog) {
2+
return dialog.querySelector(".o-dialog__header > .a-button");
3+
}
4+
5+
function openDialog(dialogId) {
6+
const dialog = document.getElementById(dialogId);
7+
if (!dialog) return;
8+
9+
dialog.showModal();
10+
}
11+
12+
function openDialogOnHash() {
13+
const hash = window.location.hash;
14+
if (!hash) return;
15+
16+
const targetId = decodeURIComponent(hash.substring(1));
17+
const targetElement = document.getElementById(targetId);
18+
19+
if (targetElement) {
20+
const dialog = targetElement.closest("dialog");
21+
if (dialog && !dialog.open) {
22+
dialog.showModal();
23+
}
24+
}
25+
}
26+
27+
function initDialogs() {
28+
document.querySelectorAll("dialog").forEach((dialog) => {
29+
dialog.addEventListener("click", (e) => {
30+
if (e.target === dialog) {
31+
dialog.close();
32+
}
33+
});
34+
35+
const closeButton = getCloseButton(dialog);
36+
if (closeButton) {
37+
closeButton.addEventListener("click", () => dialog.close());
38+
}
39+
});
40+
41+
document.querySelectorAll("[data-dialog-trigger]").forEach((trigger) => {
42+
const handler = (e) => {
43+
if (e.type === "click" || (e.type === "keydown" && e.key === "Enter")) {
44+
e.preventDefault();
45+
const dialogId = trigger.getAttribute("data-dialog-trigger");
46+
openDialog(dialogId);
47+
}
48+
};
49+
50+
trigger.addEventListener("click", handler);
51+
trigger.addEventListener("keydown", handler);
52+
});
53+
54+
// Initialize hash check
55+
openDialogOnHash();
56+
window.addEventListener("hashchange", openDialogOnHash);
57+
}
58+
59+
if (document.readyState === "loading") {
60+
document.addEventListener("DOMContentLoaded", initDialogs);
61+
} else {
62+
initDialogs();
63+
}

assets/js/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ import "./dropdown.js";
99
import "./search.js";
1010
import "./interactiveMap.js";
1111
import "./expander.js";
12+
import "./dialog.js";

assets/js/mobileMenu.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ function closeMobileMenu() {
3939
const navContainer = document.querySelector(".o-header__nav");
4040
const menuButton = document.querySelector(".o-nav__menu-button");
4141

42+
if (!navContainer.classList.contains("o-header__nav--open")) return;
43+
4244
navContainer.classList.remove("o-header__nav--open");
4345
menuButton.setAttribute("aria-expanded", false);
4446
closeOverlay();

assets/sass/button.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
display: inline-flex;
44
align-items: center;
55
gap: 0.4rem;
6-
border: 0.2rem solid var(--link-default);
76
border-radius: var(--border-radius-m);
87
font-size: 1.5rem;
98
cursor: pointer;
@@ -25,4 +24,12 @@
2524
padding: 0.6rem;
2625
display: block;
2726
}
27+
28+
&__external {
29+
border: 0.2rem solid var(--link-default);
30+
}
31+
32+
&__internal {
33+
border: none;
34+
}
2835
}

assets/sass/dialog.scss

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
.o-dialog {
2+
max-height: calc(100dvh - 14rem);
3+
overflow: auto;
4+
display: flex;
5+
flex-direction: column;
6+
7+
.a-anchorlink {
8+
margin-bottom: 0;
9+
10+
&__link {
11+
display: none;
12+
}
13+
14+
> h2 {
15+
margin-bottom: 1rem;
16+
}
17+
}
18+
19+
.o-divider {
20+
display: none;
21+
}
22+
23+
&__wrapper {
24+
width: fit-content;
25+
border: none;
26+
padding: 0;
27+
background-color: var(--bg-default);
28+
color: var(--color-body);
29+
border-radius: var(--border-radius-m);
30+
border: var(--border);
31+
overflow: hidden;
32+
33+
&::backdrop {
34+
background-color: rgba(0, 0, 0, 0.6);
35+
backdrop-filter: blur(4px);
36+
}
37+
}
38+
39+
&__header {
40+
position: sticky;
41+
top: 0;
42+
background-color: var(--bg-default);
43+
display: flex;
44+
column-gap: 1rem;
45+
align-items: center;
46+
justify-content: space-between;
47+
padding: 1rem 1rem 1rem 2rem;
48+
border-bottom: var(--border);
49+
border-color: var(--color-table-border);
50+
51+
.o-divider {
52+
display: none;
53+
}
54+
55+
> h1 {
56+
margin: 0;
57+
font-size: 2.2rem;
58+
}
59+
}
60+
61+
&__body {
62+
padding: 2rem;
63+
overflow: auto;
64+
65+
> *:last-child {
66+
margin-bottom: 0;
67+
}
68+
}
69+
}

assets/sass/header.scss

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@
102102
z-index: 14;
103103
}
104104

105-
body:has(.overlay--show) {
105+
#header:has(.overlay--dialog),
106+
.overlay--dialog {
107+
z-index: 10;
108+
}
109+
110+
body:has(.overlay--show),
111+
body:has(dialog[open]) {
106112
overflow: hidden;
107113
}

assets/sass/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
@import "tag.scss";
2424
@import "floatImage.scss";
2525
@import "teamMember.scss";
26+
@import "dialog.scss";

assets/sass/styles.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,16 @@ button {
5757
@include focus-indicator(0.2rem);
5858
}
5959

60-
a {
60+
a,
61+
.o-link {
6162
color: var(--link-default);
6263
transition:
6364
color 0.3s ease,
6465
background-color 0.3s ease;
6566
text-underline-offset: 0.2rem;
6667
border-radius: var(--border-radius-s);
68+
text-decoration: underline;
69+
cursor: pointer;
6770

6871
&:hover,
6972
&:focus {
@@ -80,6 +83,10 @@ a {
8083
display: none;
8184
}
8285
}
86+
87+
& > .material-symbols-rounded {
88+
margin: 0 0.2rem;
89+
}
8390
}
8491

8592
main {

content/country/belgium/index.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Additionally, international [Eurostar](/operator/eurostar "Eurostar") trains ope
1717
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.
1818

1919
{{< identify-operator sources="db-website,vagonweb" >}}
20-
Not all trains in the country (e. g. `ICE`) are shown in the [SNCB / NMBS online timetable](https://www.belgiantrain.be/en/).
20+
Not all trains in the country (e.g. `ICE`) are shown in the [SNCB / NMBS online timetable](https://www.belgiantrain.be/en/).
2121
{{< /identify-operator >}}
2222

2323
## Interesting

0 commit comments

Comments
 (0)