diff --git a/assets/js/darkmode.js b/assets/js/darkmode.js
index 3c8887357..b7697a9c5 100644
--- a/assets/js/darkmode.js
+++ b/assets/js/darkmode.js
@@ -26,8 +26,10 @@
const effectiveTheme = getEffectiveTheme(theme);
if (effectiveTheme === DARK_THEME) {
document.documentElement.setAttribute("data-theme", DARK_THEME);
+ document.documentElement.setAttribute("data-pf-theme", DARK_THEME);
} else {
document.documentElement.removeAttribute("data-theme");
+ document.documentElement.removeAttribute("data-pf-theme");
}
}
diff --git a/assets/js/main.js b/assets/js/main.js
index b9c687e29..250f2f335 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -6,8 +6,8 @@ import "./highlightHeadline.js";
import "./contentNavigation.js";
import "./anchorlinks.js";
import "./dropdown.js";
-import "./search.js";
import "./interactiveMap.js";
import "./expander.js";
import "./dialog.js";
import "./fipValidityComparison.js";
+import "./search.js";
diff --git a/assets/js/search.js b/assets/js/search.js
index 954153852..5c443dcda 100644
--- a/assets/js/search.js
+++ b/assets/js/search.js
@@ -1,127 +1,23 @@
-import {
- openOverlay,
- closeOverlay,
- addOverlayClickListener,
-} from "./overlay.js";
+function initMobileSearchButton() {
+ const searchButtons = document.querySelectorAll(".o-header__search-toggle");
+ const pagefindTrigger = document.querySelector("pagefind-modal-trigger");
-const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
-const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
+ if (searchButtons.length === 0 || !pagefindTrigger) return;
-const initSearch = () => {
- const search = document.getElementById("search");
- const searchButtons = document.querySelectorAll(".o-header__search");
- const isHome = document.querySelector(".o-startpage");
- let placeholderText = search.dataset.placeholder;
- let searchLabelText = search.dataset.label;
+ searchButtons.forEach((searchButton) => {
+ searchButton.addEventListener("click", () => {
+ if (typeof pagefindTrigger.openModal === "function") {
+ pagefindTrigger.openModal();
+ return;
+ }
- if (!isMobile) {
- if (isMac) {
- placeholderText += " (⌘ + K)";
- } else {
- placeholderText += " (CTRL + K)";
- }
- }
-
- new PagefindUI({
- element: "#search",
- highlightParam: "highlight",
- showSubResults: true,
- translations: {
- placeholder: placeholderText,
- search_label: searchLabelText,
- },
- });
-
- // Close keyboard when touching search results (mobile only)
- const searchDrawer = search.querySelector(".pagefind-ui__drawer");
- searchDrawer.addEventListener("touchstart", () => {
- if (!isMobile) return;
- if (document.activeElement && document.activeElement.blur) {
- document.activeElement.blur();
- }
- });
-
- const searchElement = search.querySelector("input");
-
- const updateSearchButtonLabels = (isOpen) => {
- searchButtons.forEach((button) => {
- const openLabel = button.dataset.labelOpen;
- const closeLabel = button.dataset.labelClose;
- const label = isOpen ? closeLabel : openLabel;
- button.setAttribute("aria-label", label);
- button.setAttribute("title", label);
- });
- };
-
- const closeSearch = () => {
- search.querySelector(".pagefind-ui__search-clear").click();
- closeOverlay();
- search.classList.remove("o-search--show");
- updateSearchButtonLabels(false);
- };
-
- const openSearch = () => {
- openOverlay("search");
- search.classList.add("o-search--show");
- searchElement.focus();
- search.scrollIntoView({ behavior: "smooth", block: "start" });
- updateSearchButtonLabels(true);
- };
-
- if (search && isHome) {
- searchElement.addEventListener("focus", () => {
- openSearch();
+ pagefindTrigger.querySelector("button")?.click();
});
- // If focus moves outside the search, close it
- search.addEventListener(
- "blur",
- (e) => {
- if (
- e.relatedTarget &&
- !search.contains(e.relatedTarget) &&
- !Array.from(searchButtons).includes(e.relatedTarget)
- ) {
- closeSearch();
- }
- },
- true,
- );
- }
-
- const toggleSearch = () => {
- if (search.classList.contains("o-search--show")) {
- closeSearch();
- return;
- }
- openSearch();
- };
-
- searchButtons.forEach((button) => {
- button.addEventListener("click", toggleSearch);
});
+}
- // Toggle search on Ctrl + K or Cmd + K
- document.addEventListener("keydown", (e) => {
- if ((e.ctrlKey || e.metaKey) && e.key === "k") {
- e.preventDefault();
- toggleSearch();
- }
- });
-
- // Close search on ESC
- document.addEventListener("keydown", (e) => {
- if (e.key === "Escape") {
- closeSearch();
- }
- });
-
- addOverlayClickListener(closeSearch);
-};
-
-if (document.readyState === "interactive") {
- initSearch();
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", initMobileSearchButton);
} else {
- window.addEventListener("DOMContentLoaded", () => {
- initSearch();
- });
+ initMobileSearchButton();
}
diff --git a/assets/sass/_variables.scss b/assets/sass/_variables.scss
index 05a8d2885..dc7297708 100644
--- a/assets/sass/_variables.scss
+++ b/assets/sass/_variables.scss
@@ -56,22 +56,71 @@ $highlight-colors-dark: (
default: map-get($tag-colors-dark, info),
);
-html {
- --pagefind-ui-scale: 1 !important;
- --pagefind-ui-text: #000;
+:root {
+ --font-family: "Roboto", Arial, Helvetica, sans-serif;
+
--link-default: #{$link-default};
--link-hovered: #{$link-hovered};
--link-special: #{$link-special};
+
--bg-default: #{$bg-default};
--bg-neutral: #{$bg-neutral};
--bg-accent: #{$bg-accent};
--bg-code: #{$bg-code};
+
--color-onLight: #{$color-onLight};
--color-table-border: #{$color-table-border};
--color-body: rgb(33, 37, 41);
--color-success: #096640;
--color-error: #ad1731;
+ --border-radius-s: 0.4rem;
+ --border-radius-m: 0.8rem;
+ --border-radius-l: 1.6rem;
+
+ --box-shadow: 0 0.4rem 1rem rgba(0, 0, 0, 0.25);
+ --box-shadow-light: 0.4rem 0.4rem 0.4rem rgba(0, 0, 0, 0.1);
+
+ --border: 0.1rem solid transparent;
+ --border-visible: 0.1rem solid #d0d0d0;
+ --outline-focus-indicator: #257fa8;
+
+ @media print {
+ --bg-neutral: white;
+ }
+
+ --container-max-width: 1320px;
+
+ @media (max-width: #{$breakpoint-xxl}) {
+ --container-max-width: 1140px;
+ }
+
+ @media (max-width: #{$breakpoint-xl}) {
+ --container-max-width: 960px;
+ }
+
+ @media (max-width: #{$breakpoint-lg}) {
+ --container-max-width: 720px;
+ }
+
+ @media (max-width: #{$breakpoint-md}) {
+ --container-max-width: 540px;
+ }
+
+ @media (max-width: #{$breakpoint-sm}) {
+ --container-max-width: calc(100vw - 3.2rem);
+ }
+
+ --pf-font: var(--font-family);
+ --pf-input-font-size: 1.8rem;
+ --pf-summary-font-size: 1.5rem;
+ --pf-result-title-font-size: 1.8rem;
+ --pf-result-excerpt-font-size: 1.5rem;
+ --pf-modal-max-width: var(--container-max-width);
+ --pf-outline-focus: var(--outline-focus-indicator);
+ --pf-border-radius: var(--border-radius-m);
+ --pf-background: var(--bg-default);
+
@each $name, $color in $fip-validity-colors {
--fip-validity-#{$name}: #{$color};
}
@@ -85,33 +134,18 @@ html {
--highlight-#{$name}-bg: #{mix(white, $color, 90%)};
--highlight-#{$name}-color: #{$color};
}
-
- --border-radius-s: 0.4rem;
- --border-radius-m: 0.8rem;
- --border-radius-l: 1.6rem;
- --pagefind-ui-border-radius: var(--border-radius-l) !important;
- --pagefind-ui-border: #000 !important;
- --box-shadow: 0 0.4rem 1rem rgba(0, 0, 0, 0.25);
- --box-shadow-light: 0.4rem 0.4rem 0.4rem rgba(0, 0, 0, 0.1);
- --border: 0.1rem solid transparent;
- --border-visible: 0.1rem solid #d0d0d0;
- --pagefind-ui-font: roboto, Arial, Helvetica, sans-serif;
- --outline-focus-indicator: #257fa8;
-
- @media print {
- --bg-neutral: white;
- }
}
-html[data-theme="dark"] {
+:root[data-theme="dark"] {
@media screen {
- --pagefind-ui-text: #fff;
--link-default: #ff6b3d;
--link-hovered: #ff8a5b;
--link-special: #ffffff;
+
--bg-default: #151b23;
--bg-neutral: #0d1117;
--bg-accent: #86761a;
+
--color-onLight: #ffffff;
--color-table-border: #555;
--color-body: #e0e0e0;
@@ -132,10 +166,8 @@ html[data-theme="dark"] {
--highlight-#{$name}-color: #{$color};
}
- --pagefind-ui-border: #555;
--box-shadow: 0 0.4rem 1rem rgba(0, 0, 0, 0.5);
--box-shadow-light: 0.4rem 0.4rem 0.4rem rgba(0, 0, 0, 0.3);
- --pagefind-ui-background: var(--bg-default);
--border: 0.1rem solid #3d444d;
--border-visible: 0.1rem solid #3d444d;
--outline-focus-indicator: #2e9acb;
diff --git a/assets/sass/fonts.scss b/assets/sass/fonts.scss
index 8b5202314..d5bc024a4 100644
--- a/assets/sass/fonts.scss
+++ b/assets/sass/fonts.scss
@@ -123,7 +123,7 @@
body,
button {
- font-family: "Roboto", Arial, Helvetica, sans-serif;
+ font-family: var(--font-family);
word-wrap: break-word;
hyphens: auto;
}
diff --git a/assets/sass/header.scss b/assets/sass/header.scss
index 6511f2ef5..793ec52ca 100644
--- a/assets/sass/header.scss
+++ b/assets/sass/header.scss
@@ -92,11 +92,6 @@
z-index: 6;
}
-#header:has(.overlay--search),
-.overlay--search {
- z-index: 10;
-}
-
#header:has(.overlay--mobileMenu),
.overlay--mobileMenu {
z-index: 14;
diff --git a/assets/sass/navigation.scss b/assets/sass/navigation.scss
index eec8bb683..774ee4d73 100644
--- a/assets/sass/navigation.scss
+++ b/assets/sass/navigation.scss
@@ -33,6 +33,10 @@ menu > li > menu {
padding-inline-start: 0;
}
+.o-header__utility-menu {
+ gap: 0.6rem;
+}
+
.o-header__item {
list-style: none;
display: flex;
@@ -222,6 +226,20 @@ menu > li > menu {
}
}
+.o-header__item--desktop-search {
+ @media (min-width: #{$breakpoint-md}) and (max-width: #{$breakpoint-lg}) {
+ display: none;
+ }
+}
+
+.o-header__item--desktop-search-icon {
+ display: none;
+
+ @media (min-width: #{$breakpoint-md}) and (max-width: #{$breakpoint-lg}) {
+ display: inline-flex;
+ }
+}
+
.o-header__button {
padding: 1rem;
border: none;
diff --git a/assets/sass/search.scss b/assets/sass/search.scss
index 9d777e297..d429421e7 100644
--- a/assets/sass/search.scss
+++ b/assets/sass/search.scss
@@ -1,240 +1,96 @@
-$search-z-index: 10;
-$search-z-index-focus: 12;
-
-#search {
- width: 100%;
- height: 64px;
- display: flex;
- z-index: $search-z-index;
-
- @media print {
- display: none;
- }
-
- .pagefind-ui {
+.o-startpage__search {
+ pagefind-modal-trigger {
+ display: block;
width: 100%;
- height: 100%;
-
- &__form {
- position: relative;
- height: 100%;
-
- &::before {
- content: "search";
- position: absolute;
- top: 23px;
- left: 20px;
- z-index: $search-z-index + 1;
- font-family: "Material Symbols Rounded";
- opacity: 0.7;
- pointer-events: none;
- line-height: 1;
- }
- }
-
- &__message {
- padding: 1rem;
- margin-bottom: 0;
- }
-
- &__results-area {
- max-height: 50vh;
- padding: 0 1rem;
- overflow-y: scroll;
-
- @media (max-width: #{$breakpoint-md}) {
- max-height: calc(100dvh - 17rem);
- }
- }
-
- &__results {
- padding-left: 0;
- margin-bottom: 0;
- }
- &__search-input {
- z-index: $search-z-index;
- outline: 0.2rem solid transparent;
- border: var(--border);
- box-shadow: var(--box-shadow);
- border-radius: var(--border-radius-l);
- height: 100%;
- background-color: var(--bg-default);
- color: var(--color-body);
- padding: 0 70px 0 54px;
- font-size: 2rem;
- position: relative;
- display: flex;
+ &::part(button) {
width: 100%;
- box-sizing: border-box;
- font-family: "Roboto", Arial, Helvetica, sans-serif;
-
- @include focus-indicator(0.2rem);
-
- &::placeholder {
- opacity: 0.7;
- color: var(--color-body);
- }
-
- // When results are visible
- &:has(
- + .pagefind-ui__search-clear
- + .pagefind-ui__drawer
- .pagefind-ui__results-area
- ) {
- border-radius: var(--border-radius-l) var(--border-radius-l) 0 0;
- }
- }
-
- &__search-clear {
- display: none;
- }
-
- &__suppressed {
- display: none;
}
+ }
+}
- &__drawer {
- background-color: var(--bg-default);
- overscroll-behavior: contain;
- overflow: hidden;
- position: absolute;
- width: 100%;
- z-index: $search-z-index;
- border: var(--border);
- border-radius: 0 0 var(--border-radius-l) var(--border-radius-l);
- box-sizing: border-box;
- }
-
- &__result {
- list-style-type: none;
- display: flex;
- align-items: flex-start;
- gap: 3.2rem;
- padding: 2rem 0;
- border-top: 0.2rem solid grey;
- margin: 0 1rem;
-
- &-inner,
- &-thumb {
- margin-top: 0;
- }
-
- &-thumb {
- width: 10rem;
- height: auto;
- aspect-ratio: 3 / 2;
-
- @media (max-width: #{$breakpoint-md}) {
- display: none;
- }
- }
-
- &-image {
- max-width: 100%;
- }
-
- &-title {
- display: inline-block;
- font-weight: 700;
- margin: 0;
- }
-
- &-nested {
- display: flex;
- flex-direction: column;
- padding-top: 0.8rem;
- padding-left: 2.4rem;
+pagefind-modal-trigger {
+ height: 100% !important;
+}
- .pagefind-ui__result-link {
- font-size: 1.8rem;
- }
+.pf-result-image {
+ object-fit: contain !important;
+ background-color: unset !important;
+}
- .pagefind-ui__result-link::before {
- content: "subdirectory_arrow_right";
- font-family: "Material Symbols Rounded";
- position: absolute;
- left: -2.4rem;
- }
- }
+.pf-result-excerpt {
+ display: -webkit-box !important;
+ -webkit-line-clamp: 2 !important;
+ line-clamp: 2 !important;
+ -webkit-box-orient: vertical !important;
+ white-space: wrap !important;
+}
- &-excerpt {
- margin-bottom: 0;
- margin-top: 0.4rem;
- }
- }
+.pf-heading-link {
+ font-size: 1.8rem !important;
+}
- &__result-link {
- position: relative;
- font-size: 2.2rem;
- }
+.pf-heading-excerpt {
+ font-size: 1.4rem !important;
+}
- &__button {
- border: 0.2rem solid var(--link-default);
- border-radius: var(--border-radius-m);
- background: transparent;
- color: var(--body-color);
- height: 4.8rem;
- padding: 1.2rem;
- margin-bottom: 1rem;
- width: 100%;
- text-align: center;
- font-weight: 700;
- transition:
- background 0.2s,
- color 0.2s;
+.pf-trigger-text {
+ text-transform: capitalize !important;
+ font-family: var(--font-family) !important;
+ font-size: var(--pf-input-font-size) !important;
+}
- &:hover,
- &:focus {
- background: rgba($link-hovered, 0.15);
- }
- }
+.o-startpage__search > pagefind-modal-trigger > .pf-trigger-btn {
+ box-shadow: var(--box-shadow) !important;
+ height: 100% !important;
+ border-radius: var(--border-radius-l) !important;
+}
- &__hidden {
- display: none;
- }
+.o-header__item > pagefind-modal-trigger > .pf-trigger-btn {
+ height: 4.2rem !important;
+}
- &--reset {
- mark {
- background-color: var(--bg-accent);
- color: black;
- }
- }
+.pf-result-excerpt > mark,
+.pf-heading-excerpt > mark {
+ color: var(--link-default) !important;
+}
- &__loading {
- color: var(--bg-neutral);
- background-color: var(--bg-neutral);
- border-radius: var(--border-radius-s);
- pointer-events: none;
- }
+.pagefind-highlight {
+ color: var(--color-body);
+ background: linear-gradient(
+ to right,
+ hsla(48, 92%, 75%, 0.3),
+ hsla(48, 92%, 75%, 0.58)
+ );
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ border-radius: 0.5rem;
+ padding: 0.4rem;
+ margin: 0 -0.4rem;
+ animation: pagefind-highlight-reveal 260ms ease-out;
+
+ @media (prefers-reduced-motion: reduce) {
+ animation: none;
}
}
+// The negative margin influences the box sizing in flexbox environments
+:is(h1, .o-related__item) .pagefind-highlight {
+ margin: 0;
+}
-#search.o-search {
- &--contentpage {
- position: fixed;
- display: none;
- opacity: 0;
- visibility: hidden;
- transition: opacity 0.5s ease;
+@keyframes pagefind-highlight-reveal {
+ from {
+ background-size: 0% 100%;
+ opacity: 0.7;
}
- &--show {
- display: block;
+ to {
+ background-size: 100% 100%;
opacity: 1;
- visibility: visible;
- z-index: $search-z-index-focus;
-
- input.pagefind-ui__search-input {
- z-index: $search-z-index-focus;
- }
-
- .pagefind-ui__drawer {
- z-index: $search-z-index-focus;
- }
-
- .pagefind-ui__form::before {
- z-index: $search-z-index-focus + 1;
- }
}
}
+
+.pf-result-card:focus-within,
+.pf-heading-chip:focus-within {
+ background: rgba($link-hovered, 0.15) !important;
+}
diff --git a/assets/sass/startpage.scss b/assets/sass/startpage.scss
index d45f28edd..f1c91e8a0 100644
--- a/assets/sass/startpage.scss
+++ b/assets/sass/startpage.scss
@@ -81,6 +81,7 @@
.o-startpage__search {
margin-bottom: 2rem;
+ height: 6rem;
width: 100%;
@media print {
diff --git a/assets/sass/styles.scss b/assets/sass/styles.scss
index 8dad07a23..2ed5ff3fe 100644
--- a/assets/sass/styles.scss
+++ b/assets/sass/styles.scss
@@ -46,7 +46,7 @@ ol {
@mixin focus-indicator($offset) {
&:focus,
&:focus-visible {
- outline: var(--outline-focus-indicator) solid 0.2rem;
+ outline: var(--outline-focus-indicator) solid 2px;
outline-offset: $offset;
}
}
@@ -100,27 +100,7 @@ main {
}
.o-container {
- max-width: 1320px;
-
- @media (max-width: #{$breakpoint-xxl}) {
- max-width: 1140px;
- }
-
- @media (max-width: #{$breakpoint-xl}) {
- max-width: 960px;
- }
-
- @media (max-width: #{$breakpoint-lg}) {
- max-width: 720px;
- }
-
- @media (max-width: #{$breakpoint-md}) {
- max-width: 540px;
- }
-
- @media (max-width: #{$breakpoint-sm}) {
- max-width: calc(100vw - 3.2rem);
- }
+ max-width: var(--container-max-width);
@media print {
max-width: 100%;
@@ -392,12 +372,6 @@ figure {
border: none;
}
-.pagefind-highlight {
- padding: 0;
- background-color: var(--bg-accent);
- color: black;
-}
-
.sr-only {
opacity: 0;
position: absolute;
diff --git a/i18n/de.yaml b/i18n/de.yaml
index 8a806a9ba..031d466d9 100644
--- a/i18n/de.yaml
+++ b/i18n/de.yaml
@@ -131,9 +131,6 @@ menu:
dropdown-label: Verfügbare Betreiber
label: Betreiber
title: Betreiber-Dropdown öffnen
- search:
- close: Suche schließen
- open: Suche öffnen
theme:
switch-to-auto: Zu automatischem Modus wechseln
switch-to-dark: Zu dunklem Modus wechseln
@@ -166,9 +163,6 @@ satellite:
kostenlose Minuten pro Monat ins Ausland verfügbar. Für die Registrierung
wird ein deutscher Wohnsitz benötigt und die Registrierung kann einige Tage
in Anspruch nehmen.
-search:
- label: Durchsuche alle Seiteninhalte
- placeholder: Suche
skipToContent: Zum Inhalt springen
support:
text: >-
diff --git a/i18n/en.yaml b/i18n/en.yaml
index 7744391b1..c670f056e 100644
--- a/i18n/en.yaml
+++ b/i18n/en.yaml
@@ -128,9 +128,6 @@ menu:
dropdown-label: Available operators
label: Operators
title: Open Operator-Dropdown
- search:
- close: Close search
- open: Open search
theme:
switch-to-auto: Switch to auto mode
switch-to-dark: Switch to dark mode
@@ -159,9 +156,6 @@ satellite:
[Satellite](https://www.satellite.me/). It offers 100 free minutes per month
for international calls. A German residence is required for registration and
registration may take a few days.
-search:
- label: Search all page content
- placeholder: Search
skipToContent: Skip to content
support:
text: >-
diff --git a/i18n/fr.yaml b/i18n/fr.yaml
index ae233dbd4..cc7bbad57 100644
--- a/i18n/fr.yaml
+++ b/i18n/fr.yaml
@@ -133,9 +133,6 @@ menu:
dropdown-label: Opérateurs disponibles
label: Opérateurs
title: Ouvrir la liste déroulante de l'opérateur
- search:
- close: Fermer la recherche
- open: Ouvrir la recherche
theme:
switch-to-auto: Passer en mode automatique
switch-to-dark: Passer en mode sombre
@@ -165,9 +162,6 @@ satellite:
offre 100 minutes gratuites par mois pour les appels internationaux. Une
résidence allemande est requise pour l'inscription et l'inscription peut
prendre quelques jours.
-search:
- label: Rechercher dans tout le contenu de la page
- placeholder: Rechercher
skipToContent: Aller au contenu
support:
text: >-
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index de2526dfe..7652f8e14 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -27,17 +27,10 @@
{{- end -}}
>
- {{- if not .IsHome -}}
-
- {{ end }}
{{ block "main" . }}{{ end }}
+
{{ if or (eq .Page.Type "country") (eq .Page.Type "operator") (eq .Page.Type "generalinformation") }}
{{ partial "snackbar" . }}
diff --git a/layouts/_default/home.html b/layouts/_default/home.html
index 4d27432ac..16c7611cf 100644
--- a/layouts/_default/home.html
+++ b/layouts/_default/home.html
@@ -12,12 +12,7 @@
diff --git a/layouts/country/single.html b/layouts/country/single.html
index 6003ca531..dd42afd59 100644
--- a/layouts/country/single.html
+++ b/layouts/country/single.html
@@ -4,7 +4,7 @@