From 637e97bebd461cfbf1c9c40d77e1363b8f54354b Mon Sep 17 00:00:00 2001
From: Olivia Simonet <91660674+Olivia206@users.noreply.github.com>
Date: Thu, 26 Dec 2024 16:47:15 +0100
Subject: [PATCH] =?UTF-8?q?Permettre=20d'ouvrir=20la=20modale=20de=20reche?=
 =?UTF-8?q?rche=20avec=20les=20diff=C3=A9rentes=20options=20de=20config=20?=
 =?UTF-8?q?(#798)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Alexis BENOIT <alex@noesya.coop>
---
 assets/js/theme/design-system/mainMenu.js     |   6 +-
 assets/js/theme/design-system/search.js       | 304 ++++++++----------
 assets/js/theme/index.js                      |   2 +-
 .../sass/_theme/configuration/components.sass |  10 +-
 assets/sass/_theme/configuration/zindex.sass  |   3 +-
 assets/sass/_theme/design-system/footer.sass  |   2 +
 assets/sass/_theme/design-system/header.sass  |  34 +-
 assets/sass/_theme/design-system/nav.sass     |  10 +-
 assets/sass/_theme/design-system/search.sass  | 164 ++++------
 hugo.yaml                                     |   7 +-
 layouts/_default/baseof.html                  |  10 +-
 layouts/partials/commons/menu.html            |   7 +-
 layouts/partials/commons/search/button.html   |   9 +
 layouts/partials/commons/search/modal.html    |  10 +
 layouts/partials/footer/footer-simple.html    |  11 +-
 layouts/partials/header/header.html           |   2 +-
 layouts/partials/header/search.html           |  15 -
 17 files changed, 277 insertions(+), 329 deletions(-)
 create mode 100644 layouts/partials/commons/search/button.html
 create mode 100644 layouts/partials/commons/search/modal.html
 delete mode 100644 layouts/partials/header/search.html

diff --git a/assets/js/theme/design-system/mainMenu.js b/assets/js/theme/design-system/mainMenu.js
index aefb57c9..5bac0db7 100644
--- a/assets/js/theme/design-system/mainMenu.js
+++ b/assets/js/theme/design-system/mainMenu.js
@@ -76,8 +76,10 @@ class MainMenu {
     }
 
     resize () {
-        document.documentElement.style.setProperty('--header-height', this.element.offsetHeight + 'px');
-        document.documentElement.style.setProperty('--header-menu-max-height', window.innerHeight - this.element.offsetHeight + 'px');
+        if (!this.state.isOpened) {
+            document.documentElement.style.setProperty('--header-height', this.element.offsetHeight + 'px');
+            document.documentElement.style.setProperty('--header-menu-max-height', window.innerHeight - this.element.offsetHeight + 'px');
+        }
 
         // is state changed ?
         if (this.state.isMobile === isMobile()) {
diff --git a/assets/js/theme/design-system/search.js b/assets/js/theme/design-system/search.js
index 08c99edd..73e5a2ad 100644
--- a/assets/js/theme/design-system/search.js
+++ b/assets/js/theme/design-system/search.js
@@ -1,196 +1,168 @@
-/* eslint-disable no-undef */
-import { ariaHideBodyChildren } from '../utils/a11y';
-import { focusTrap } from '../utils/focus-trap';
+/* eslint-disable no-undef, no-underscore-dangle */
+window.osuny = window.osuny || {};
+window.osuny.Search = window.osuny.Search || {};
 
-const CLASSES = {
-    modalOpened: 'has-search-opened'
+window.osuny.Search = function (element) {
+    window.osuny.Popup.call(this, element);
+
+    this.buttons = document.querySelectorAll('.search-button');
+
+    this._setup();
+    this._listen();
+};
+
+window.osuny.Search.prototype = Object.create(window.osuny.Popup.prototype);
+
+window.osuny.Search.prototype._setup = function () {
+    this.setPageFind();
+    this.setAccessibility();
+};
+
+window.osuny.Search.prototype.setPageFind = function () {
+    this.pageFindUI = new PagefindUI({
+        element: this.element,
+        showSubResults: true
+    });
+
+    // Listen to user's input
+    this.input = document.querySelector('.pagefind-ui__search-input');
 };
 
-class Search {
-    constructor (container) {
-        this.state = {
-            isOpened: false
-        };
-        this.button = document.querySelector('.pagefind-ui__toggle');
-        this.element = document.querySelector('.search__modal');
-        this.closeButton = this.element.querySelector('.search__close');
-        // this.a11yButton = document.querySelector('[href="#search-button"]');
-
-        this.searchInstance = new PagefindUI({
-            element: container,
-            showSubResults: true
-        });
-
-        if (!this.element) {
-            return;
+window.osuny.Search.prototype._listen = function () {
+    var inPageWithToc = document.body.querySelector('.toc-cta');
+    window.osuny.Popup.prototype._listen.call(this);
+
+    this.buttons.forEach(function (button) {
+        button.addEventListener('click', this.toggle.bind(this, true, button));
+        if (inPageWithToc) {
+            button.classList.add('in-page-with-toc');
         }
+    }.bind(this));
 
-        this.listen();
-        this.setAccessibility();
-    }
+    this.input.addEventListener('input', this.onInputChange.bind(this));
 
-    setAccessibility () {
-        const input = document.querySelector('.pagefind-ui__search-input'),
-            // Delay before screen readers speak results message
-            speakDelay = 1500;
-        input.setAttribute('title', input.getAttribute('placeholder'));
-
-        // Add element to alert screen reader of the search results
-        this.accessibleMessageContainer = document.createElement('div');
-        this.element.append(this.accessibleMessageContainer);
-        this.accessibleMessageContainer.setAttribute('aria-live', 'polite');
-        this.accessibleMessageContainer.setAttribute('aria-atomic', 'true');
-        this.accessibleMessageContainer.classList.add('sr-only', 'pagefind-ui__accessible-message');
-
-        input.addEventListener('input', () => {
-            this.accessibleMessageContainer.innerHTML = '';
-            if (input.value !== '') {
-                this.accessibleMessage = document.createElement('p');
-                this.accessibleMessageContainer.appendChild(this.accessibleMessage);
-            }
-            clearTimeout(this.a11yTimeout);
-            this.a11yTimeout = setTimeout(this.updateAccessibility.bind(this), speakDelay);
-        });
-    }
+    this.observeMutations();
+};
 
-    updateAccessibility () {
-        this.updateAccessibilityMessageRole();
-        this.updateAccessibilityTags();
+window.osuny.Search.prototype.observeMutations = function () {
+    var previousResults = [],
+        results = [],
+        firstResult;
+
+    this.observer = new MutationObserver(function () {
+        results = this.element.querySelectorAll('.pagefind-ui__result');
+        if (results.length > 0 && previousResults.length > 0 && results.length !== previousResults.length) {
+            firstResult = results[previousResults.length];
+            setTimeout(this.focusFirstNextResult.bind(firstResult), 100);
+        }
+        previousResults = results;
+    }.bind(this));
+
+    this.observer.observe(this.element, { childList: true, subtree: true });
+};
+
+window.osuny.Search.prototype.focusFirstNextResult = function () {
+    var anchor = this.querySelector('a');
+    if (anchor) {
+        anchor.focus();
     }
+};
 
-    updateAccessibilityTags () {
-        const results = this.element.querySelectorAll('.pagefind-ui__result');
+window.osuny.Search.prototype.onInputChange = function () {
+    // Delay before screen readers speak results message
+    var speakDelay = 1500;
 
-        results.forEach(this.updateAccessibilityResult);
+    // Clear aria live
+    this.accessibleMessageContainer.innerHTML = '';
+    clearTimeout(this.a11yTimeout);
+    this.a11yTimeout = setTimeout(this.updateAccessibility.bind(this), speakDelay);
+
+};
+
+window.osuny.Search.prototype.toggle = function (open, triggerElement) {
+    window.osuny.Popup.prototype.toggle.call(this, open, triggerElement);
+    if (this.state.opened) {
+        this.input.focus();
+    } else {
+        this.clear();
     }
+};
 
-    updateAccessibilityResult (result) {
-        let image = result.querySelector('img'),
-            title = result.querySelector('.pagefind-ui__result-title');
+window.osuny.Search.prototype.clear = function () {
+    var button = this.element.querySelector('.pagefind-ui__button'),
+        message = this.element.querySelector('.pagefind-ui__message'),
+        results = this.element.querySelector('.pagefind-ui__results');
 
-        if (image) {
-            image.setAttribute('alt', '');
-        }
-        if (title) {
-            title.setAttribute('role', 'heading');
-            title.setAttribute('aria-level', '2');
-        }
+    if (this.input) {
+        this.input.value = '';
     }
 
-    updateAccessibilityMessageRole () {
-        const message = this.element.querySelector('.pagefind-ui__message');
-        if (!message) {
-            return;
-        }
-        message.setAttribute('aria-hidden', 'true');
-        this.accessibleMessage.innerText = message.innerText;
+    if (button) {
+        button.parentElement.removeChild(button);
     }
 
-    listen () {
-        if (document.body.querySelector('.toc-cta')) {
-            this.button.classList.add('in-page-with-toc');
-        }
-        this.button.addEventListener('click', () => {
-            this.toggle(true);
-            this.removedItems = this.element.querySelector('.pagefind-ui__suppressed', '.pagefind-ui__search-clear');
-            if (this.removedItems) {
-                this.removedItems.remove();
-            }
-        });
-        this.closeButton.addEventListener('click', () => {
-            this.clearSearch();
-            this.toggle(false);
-        });
-
-        window.addEventListener('keydown', (event) => {
-            if (event.keyCode === 27 || event.key === 'Escape') {
-                if (this.state.isOpened) {
-                    this.toggle(false);
-                    this.button.focus();
-                }
-            } else if (event.key === 'Tab' && this.state.isOpened) {
-                focusTrap(event, this.element, this.state.isOpened);
-            }
-            this.buttonMore = this.element.querySelector('.pagefind-ui__results + button');
-            if (this.buttonMore && this.state.isOpened) {
-                this.buttonMore.addEventListener('click', () => {
-                    this.buttonMoreFocus();
-                });
-            }
-        });
-
-        // if (this.a11yButton) {
-        //     a11yClick(this.a11yButton, (event) => {
-        //         if (isMobile()) {
-        //             event.preventDefault();
-        //             this.toggle(true);
-        //         }
-        //     });
-        // }
+    if (message) {
+        message.innerText = '';
     }
 
-    clearSearch () {
-        const button = this.element.querySelector('.pagefind-ui__button'),
-            message = this.element.querySelector('.pagefind-ui__message'),
-            results = this.element.querySelector('.pagefind-ui__results');
+    if (results) {
+        results.innerHTML = '';
+    }
+};
 
-        if (this.input) {
-            this.input.value = '';
-            this.searchInstance.triggerSearch(false);
-        }
+window.osuny.Search.prototype.setAccessibility = function () {
+    this.input.setAttribute('title', this.input.getAttribute('placeholder'));
 
-        if (message) {
-            message.innerText = '';
-        }
-        if (results) {
-            results.innerHTML = '';
-        }
-        if (button) {
-            button.parentElement.removeChild(button);
-        }
-    }
+    // Add element to alert screen reader of the search results
+    this.accessibleMessageContainer = document.createElement('div');
+    this.element.append(this.accessibleMessageContainer);
+    this.accessibleMessageContainer.setAttribute('aria-live', 'polite');
+    this.accessibleMessageContainer.setAttribute('aria-atomic', 'true');
+    this.accessibleMessageContainer.classList.add('sr-only', 'pagefind-ui__accessible-message');
+};
+
+window.osuny.Search.prototype.updateAccessibility = function () {
+    this.updateAccessibilityMessage();
+    this.updateAccessibilityTags();
+};
+
+window.osuny.Search.prototype.updateAccessibilityTags = function () {
+    var results = this.element.querySelectorAll('.pagefind-ui__result');
+    results.forEach(this.updateAccessibilityResult);
+};
 
-    buttonMoreFocus () {
-        const observer = new MutationObserver(mutations => {
-            mutations.forEach(mutation => {
-                mutation.addedNodes.forEach(addedNode => {
-                    if (addedNode instanceof HTMLAnchorElement) {
-                        addedNode.focus();
-                    }
-                });
-            });
-        });
-
-        observer.observe(this.element, { childList: true, subtree: true });
+window.osuny.Search.prototype.updateAccessibilityResult = function (result) {
+    var image = result.querySelector('img'),
+        title = result.querySelector('.pagefind-ui__result-title');
+
+    if (image) {
+        image.setAttribute('alt', '');
     }
 
-    toggle(open = !this.state.isOpened) {
-        this.state.isOpened = open;
-        this.element.setAttribute('aria-hidden', !this.state.isOpened);
-        this.button.setAttribute('aria-expanded', this.state.isOpened);
-
-        const classAction = this.state.isOpened ? 'add' : 'remove';
-        document.documentElement.classList[classAction](CLASSES.modalOpened);
-
-        if (open) {
-            this.input = this.element.querySelector('input');
-            this.input.focus();
-        } else {
-            document.body.style.overflow = 'unset';
-            this.button.focus();
-            this.accessibleMessageContainer.innerHTML = '';
-        }
-        ariaHideBodyChildren(this.element, open);
+    if (title) {
+        title.setAttribute('role', 'heading');
+        title.setAttribute('aria-level', '2');
     }
-}
+};
 
-// Selectors
-window.addEventListener('DOMContentLoaded', () => {
-    const pageFindContainer = document.querySelector('#search');
+window.osuny.Search.prototype.updateAccessibilityMessage = function () {
+    var message = this.element.querySelector('.pagefind-ui__message');
+    if (!message) {
+        return;
+    }
+    message.setAttribute('aria-hidden', 'true');
 
-    if (typeof PagefindUI === 'undefined') return;
+    if (this.input.value !== '') {
+        this.accessibleMessage = document.createElement('p');
+        this.accessibleMessage.innerText = message.innerText;
+        this.accessibleMessageContainer.appendChild(this.accessibleMessage);
+    }
+};
 
-    if (pageFindContainer) {
-        new Search(pageFindContainer);
+// Selectors
+window.addEventListener('DOMContentLoaded', function () {
+    var element = document.querySelector('#search');
+    if (typeof PagefindUI !== 'undefined' && element) {
+        window.osuny.search = new window.osuny.Search(element);
     }
 });
diff --git a/assets/js/theme/index.js b/assets/js/theme/index.js
index 15b53a72..98748c56 100644
--- a/assets/js/theme/index.js
+++ b/assets/js/theme/index.js
@@ -13,11 +13,11 @@ import './design-system/mainMenu';
 import './design-system/modal';
 import './design-system/navAccessibility';
 import './design-system/notes';
-import './design-system/search';
 import './design-system/toc';
 import './design-system/Popup';
 import './design-system/Lightbox';
 import './design-system/sliders';
+import './design-system/search';
 
 import './blocks/keyFigures';
 import './blocks/timeline';
diff --git a/assets/sass/_theme/configuration/components.sass b/assets/sass/_theme/configuration/components.sass
index e3934f6f..404179f9 100644
--- a/assets/sass/_theme/configuration/components.sass
+++ b/assets/sass/_theme/configuration/components.sass
@@ -134,4 +134,12 @@ $toc-overlay-color: $body-overlay-color !default
 $table-head-font-size: $h4-size !default
 $table-head-font-size-desktop: $h4-size-desktop !default
 $table-body-size: $body-size !default
-$table-body-size-desktop: $body-size-desktop !default
\ No newline at end of file
+$table-body-size-desktop: $body-size-desktop !default
+
+// Search
+$search-button-header-icon: true
+$search-button-header-text: false
+$search-button-footer-icon: true
+$search-button-footer-text: true
+$search-button-fixed-icon: true
+$search-button-fixed-text: true
\ No newline at end of file
diff --git a/assets/sass/_theme/configuration/zindex.sass b/assets/sass/_theme/configuration/zindex.sass
index 5ce2dea0..43a5236a 100644
--- a/assets/sass/_theme/configuration/zindex.sass
+++ b/assets/sass/_theme/configuration/zindex.sass
@@ -3,11 +3,12 @@ $zindex-aside: 48 !default
 $zindex-body-overlay: 51 !default
 $zindex-dropdown: 3 !default
 $zindex-footer: 50 !default
-$zindex-header: 52 !default
+$zindex-header: 55 !default
 $zindex-lightbox: 80 !default
 $zindex-modal: 72 !default
 $zindex-nav-accessibility: 1010 !default
 $zindex-toc: 50 !default
 $zindex-toc-cta: 49 !default
 $zindex-toc-offcanvas: 60 !default
+$zindex-search-button-fixed: 51 !default
 $zindex-stretched-link: 2 !default
\ No newline at end of file
diff --git a/assets/sass/_theme/design-system/footer.sass b/assets/sass/_theme/design-system/footer.sass
index f51728d2..c8b882ef 100644
--- a/assets/sass/_theme/design-system/footer.sass
+++ b/assets/sass/_theme/design-system/footer.sass
@@ -27,6 +27,8 @@ footer#document-footer
             + .container,
             > * + *
                 margin-top: $spacing-5
+            + .footer-search
+                margin-top: 0
 
     @include media-breakpoint-up(desktop)
         .container
diff --git a/assets/sass/_theme/design-system/header.sass b/assets/sass/_theme/design-system/header.sass
index 297bfcfb..a898badc 100644
--- a/assets/sass/_theme/design-system/header.sass
+++ b/assets/sass/_theme/design-system/header.sass
@@ -4,7 +4,6 @@ header#document-header
     color: $header-color
     position: fixed
     left: 0
-    transition: transform $header-sticky-transition, background $header-sticky-transition
     top: 0
     width: 100%
     z-index: $zindex-header
@@ -32,9 +31,9 @@ header#document-header
                 background: $header-sticky-dropdown-background
                 color: $header-sticky-dropdown-color
     &.is-sticky
-        .pagefind-ui__toggle
+        .search-button
             color: $header-sticky-color
-    html.is-scrolling-down:not(.has-menu-opened, .has-modal-opened, .has-search-opened) &
+    html.is-scrolling-down:not(.has-menu-opened, .has-modal-opened) &
         @include media-breakpoint-down(desktop)
             transform: translateY(-100%)
         @include media-breakpoint-up(desktop)
@@ -95,28 +94,27 @@ header#document-header
         .nav-level-1
             a
                 text-decoration: none
-            > li:not(.nav-search)
+            > li
                 line-height: 1
                 border: none
+                display: flex
+                align-items: center
                 @include media-breakpoint-down(desktop)
                     height: 100%
-                a,
-                span,
-                button
+                > a,
+                > span
                     display: block
-                    padding: 0
                     white-space: nowrap
+                    line-height: 1
+                > *
                     @include media-breakpoint-up(desktop)
                         padding: $header-upper-menu-padding-y 0
-                    @include media-breakpoint-down(desktop)
-                        line-height: $header-upper-menu-mobile-height
-
-                    // apply active style to active page (default) or active site
-                    $upper-menu-active-selector: '.active'
-                    @if $header-upper-menu-active-style-for-sites
-                        $upper-menu-active-selector: ':not([href*="https://"], [href*="http://"])'
-                    &#{$upper-menu-active-selector}
-                        box-shadow: $header-upper-menu-active-box-shadow
+                // apply active style to active page (default) or active site
+                $upper-menu-active-selector: '.active'
+                @if $header-upper-menu-active-style-for-sites
+                    $upper-menu-active-selector: ':not([href*="https://"], [href*="http://"])'
+                a#{$upper-menu-active-selector}
+                    box-shadow: $header-upper-menu-active-box-shadow
     @include media-breakpoint-down(desktop)
         &.has-upper-menu
             .menu
@@ -166,7 +164,7 @@ body
             opacity: 0
 
 header#document-header
-    nav:not(.upper-menu)
+    nav.primary-menu
         padding-bottom: $header-nav-padding-y
         padding-top: $header-nav-padding-y
         @include media-breakpoint-up(desktop)
diff --git a/assets/sass/_theme/design-system/nav.sass b/assets/sass/_theme/design-system/nav.sass
index a3e82d6b..73bafafd 100644
--- a/assets/sass/_theme/design-system/nav.sass
+++ b/assets/sass/_theme/design-system/nav.sass
@@ -140,7 +140,7 @@
 
     @include media-breakpoint-up(desktop)
         .nav-level-1
-            align-items: center
+            align-items: baseline
         .nav-level-3
             li
                 margin-top: $spacing-2
@@ -209,18 +209,18 @@
             text-decoration: none
         .nav-level-1
             display: block
-            li 
-                a, span
+            li
+                > a, > span
                     padding: $spacing-1 0
                     display: block
             > li:not(:last-child) 
                 border-bottom: 1px solid $color-border
             > li
-                > a, > span
+                > a, > span, > button
                     padding-bottom: $spacing-3
                     padding-top: $spacing-3
             li.has-children
-                [role="button"]
+                [role="button"], button
                     align-items: center
                     display: flex
                     justify-content: space-between
diff --git a/assets/sass/_theme/design-system/search.sass b/assets/sass/_theme/design-system/search.sass
index 2cc36b35..a98d764a 100644
--- a/assets/sass/_theme/design-system/search.sass
+++ b/assets/sass/_theme/design-system/search.sass
@@ -1,49 +1,13 @@
-.pagefind-ui__toggle, 
-.pagefind-ui__button, 
+.search-button,
+.pagefind-ui__button,
 .search__close
     @include button-reset
     @include meta
     &:focus
         box-shadow: none
-.pagefind-ui__toggle:not(.pagefind-primary), 
-.pagefind-ui__button, 
-.search__close
     @include meta
     color: var(--color-text)
-.pagefind-ui__toggle
-    color: $header-color
-    cursor: pointer
-    text-align: left
-    box-shadow: none
-    &:not(.toggle-text)
-        @include icon(search-line, after)
-        &::after
-            line-height: inherit
-            margin-left: $spacing-1
-    &:not(.pagefind-primary)
-        padding: $spacing-1 $spacing-2
-    &.toggle-both
-        .menu & span
-            padding-right: 0
-    span,
-    &::after
-        display: inline
-    @include media-breakpoint-down(desktop)
-        &.pagefind-primary
-            padding: $spacing-3 0
-            width: 100%
-    @include media-breakpoint-up(desktop)
-        &.toggle-icon::after
-                margin-left: 0
-    .upper-menu &
-        &.toggle-both,
-        &.toggle-text
-            white-space: nowrap
-            padding: 0
-        @include media-breakpoint-down(desktop)
-            &.toggle-both::after
-                margin-left: space()
-            
+
 .search__close
     @include icon-block(close-line, after)
     position: fixed
@@ -58,9 +22,11 @@
     @include media-breakpoint-down(desktop)
         right: $spacing-3
         top: $spacing-1
+
 #search
     background: var(--color-background)
     color: var(--color-text)
+    display: none
     height: 100vh
     left: 0
     padding-bottom: $spacing-5
@@ -74,11 +40,12 @@
     z-index: 80
     @include media-breakpoint-up(desktop)
         padding-top: $spacing-4
-    &[aria-hidden=true]
-        display: none
+    &.is-opened
+        display: block
     a
         color: var(--color-text)
     .pagefind-ui
+        // Used to hide results behind search input
         &::before
             content: ""
             background: var(--color-background)
@@ -187,66 +154,69 @@
             &__results-area
                 padding-top: space(17)
 
-.menu .nav-level-1 > li .pagefind-ui__toggle:not(.toggle-icon)::after
-    margin-left: 0
-    margin-top: pxToRem(2)
+// Toggle button appareance
+
+.search-button
+    align-items: baseline
+    cursor: pointer
+    display: flex
+    gap: $spacing-1
+    padding: 0
+    text-align: left
+    white-space: nowrap
+    line-height: 1
 
-.pagefind-fixed
+// Can be with icon only, text only, or both
+.search-button
     align-items: center
-    background: var(--color-background-alt)
-    bottom: 0
-    color: var(--color-text)
     display: flex
+    gap: $spacing-1
     justify-content: space-between
-    left: var(--grid-gutter)
-    position: fixed
-    z-index: 10
-    @include media-breakpoint-up(desktop)
-        &:not(.toggle-icon)
-            min-width: columns(2)
-        &.toggle-icon:not(:hover)
-            padding-left: 0
-            padding-right: 0
-            justify-content: center
-        &.toggle-icon
-            min-height: pxToRem(37)
-            width: pxToRem(50)
+    text-align: left
+    white-space: nowrap
+    line-height: 1
+    &::after
+        line-height: inherit
+    &--primary, &--upper-menu
+        align-items: baseline
+        color: $header-color
+        @if not $search-button-header-text
             span
-                display: none
-            &:hover,
-            &:focus
-                min-width: columns(2)
-                span
-                    display: inline
-    @include media-breakpoint-down(desktop)
-        left: 0
-        width: 100vw
-        &.in-page-with-toc
-            background: var(--color-background)
-            border-top: 1px solid #eee
-            bottom: pxToRem(44)
-            
-footer#document-footer .footer-search
-    .pagefind-footer
+                @extend .sr-only
+        @if $search-button-header-icon
+            @include icon(search-line, after)
+    &--primary
+        width: 100%
+    &--footer
         color: $footer-color
         padding: 0
-        &.toggle-icon
-            transform: translateX(-35%)
-        &::after
-            margin-top: pxToRem(3)
-    #search
-        margin-top: 0
-        a
-            color: var(--color-text)
-
-.nav-search
-    display: flex
-    .pagefind-primary:not(.toggle-icon)::after
-        margin-top: 10px
-
-.menu .nav-level-1 > li .pagefind-ui__toggle span
-    display: inline
-@include media-breakpoint-up(desktop)
-    .nav-level-1
-        > li .pagefind-ui__toggle.toggle-icon span
-            display: none
\ No newline at end of file
+        @if not $search-button-footer-text
+            span
+                @extend .sr-only
+        @if $search-button-footer-icon
+            @include icon(search-line, after)
+    &--fixed
+        background: var(--color-background-alt)
+        bottom: 0
+        color: var(--color-text)
+        left: var(--grid-gutter)
+        min-height: $minimum-accessible-size
+        padding: $spacing-1 $spacing-2
+        position: fixed
+        z-index: $zindex-search-button-fixed
+        @if not $search-button-fixed-text
+            span
+                @extend .sr-only
+        @if $search-button-fixed-icon
+            @include icon(search-line, after)
+        @include media-breakpoint-down(desktop)
+            left: 0
+            width: 100vw
+            &.in-page-with-toc
+                background: var(--color-background)
+                border-top: 1px solid #eee
+                bottom: pxToRem(44)
+                padding: 0 var(--grid-gutter)
+        @include media-breakpoint-up(desktop)
+            @if $search-button-fixed-text
+                width: columns(2)
diff --git a/hugo.yaml b/hugo.yaml
index b6309e2d..aac508c6 100644
--- a/hugo.yaml
+++ b/hugo.yaml
@@ -57,8 +57,11 @@ params:
     position: hero # hero | content
   search:
     active: false
-    position: primary # primary | upper-menu | fixed | footer
-    appearance: icon # icon | text | both
+    positions:
+      - primary
+      # - upper-menu
+      # - fixed
+      # - footer
   home:
     head:
       title: both # both | page | site
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index b848f7ab..9fd3884b 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -16,19 +16,13 @@
     {{- partial "hooks/before-header" . -}}
     {{- partial "header/header.html" . -}}
     <main{{ if .Params.contents }} class="page-with-blocks"{{ end }} id="main">
-      {{ if and (site.Params.search.active) (eq site.Params.search.position "fixed")}}
-        {{ partial "header/search.html"
-          (dict
-              "position" "fixed"
-              "context" .
-          ) 
-        }}
-      {{ end }}
+      {{ partial "commons/search/button.html" "fixed" }}
       {{- block "main" . }}{{- end }}
       {{- partial "hooks/before-main-end" . -}}
     </main>
     {{- partial "footer/footer.html" . -}}
     {{- partial "commons/lightbox/lightbox.html" . -}}
+    {{- partial "commons/search/modal.html" . -}}
     {{- partial "footer/plausible.html" . -}}
     {{- partial "footer/js.html" . -}}
     {{- partial "footer/script.html" . -}}
diff --git a/layouts/partials/commons/menu.html b/layouts/partials/commons/menu.html
index 06d3a7dc..7a7a93f7 100644
--- a/layouts/partials/commons/menu.html
+++ b/layouts/partials/commons/menu.html
@@ -98,12 +98,9 @@
     {{- end -}}
   {{ end -}}
   
-  {{ if and site.Params.search.active (eq site.Params.search.position $kind) }}
+  {{ if and site.Params.search.active (in site.Params.search.positions $kind) }}
     <li class="nav-search">
-      {{ partial "header/search.html" (dict
-          "position" $kind
-          "context" .
-      )}}
+      {{ partial "commons/search/button.html" $kind }}
     </li>
   {{ end }}
   {{ if .i18n }}
diff --git a/layouts/partials/commons/search/button.html b/layouts/partials/commons/search/button.html
new file mode 100644
index 00000000..c179e9c7
--- /dev/null
+++ b/layouts/partials/commons/search/button.html
@@ -0,0 +1,9 @@
+{{ $position := . }}
+{{ if and site.Params.search.active (in site.Params.search.positions $position) }}
+  <button
+      class="search-button search-button--{{ $position }}" 
+      aria-expanded="false" 
+      aria-label='{{- i18n (printf "commons.search.title") -}}'>
+    <span>{{- i18n (printf "commons.search.title") -}}</span>
+  </button>
+{{ end }}
\ No newline at end of file
diff --git a/layouts/partials/commons/search/modal.html b/layouts/partials/commons/search/modal.html
new file mode 100644
index 00000000..0fe401e3
--- /dev/null
+++ b/layouts/partials/commons/search/modal.html
@@ -0,0 +1,10 @@
+{{ if site.Params.search.active }}
+    <script src="/pagefind/pagefind-ui.js"></script>
+
+    <div id="search" class="search" aria-hidden="true" aria-modal="true" role="dialog" aria-label="{{ i18n "commons.search.label" }}">
+        <button class="search__close popup-close" aria-label="{{ i18n "commons.search.close" }}">
+            {{ i18n "commons.search.close" }}
+        </button>
+        <p role="heading" aria-level="1" class="sr-only">{{ i18n "commons.search.title" }}</p>
+    </div>
+{{ end }}
\ No newline at end of file
diff --git a/layouts/partials/footer/footer-simple.html b/layouts/partials/footer/footer-simple.html
index 1764854f..2e09e217 100644
--- a/layouts/partials/footer/footer-simple.html
+++ b/layouts/partials/footer/footer-simple.html
@@ -7,16 +7,13 @@
   </div>
 </div>
 {{ partial "footer/i18n.html" . }}
-{{ if and (site.Params.search.active) (eq site.Params.search.position "footer")}}
+
+{{ if in site.Params.search.positions "footer" }}
   <div class="container footer-search">
-    {{ partial "header/search.html"
-      (dict
-          "position" "footer"
-          "context" .
-      )
-    }}
+    {{ partial "commons/search/button.html" "footer" }}
   </div>
 {{ end }}
+
 <div class="container">
   <div class="footer-social">
     {{ partial "footer/social.html" }}
diff --git a/layouts/partials/header/header.html b/layouts/partials/header/header.html
index ae54414e..7bc80938 100644
--- a/layouts/partials/header/header.html
+++ b/layouts/partials/header/header.html
@@ -18,7 +18,7 @@
       </div>
     </nav>
   {{ end }}
-  <nav aria-label="{{ i18n "commons.menu.main" }}">
+  <nav class="primary-menu" aria-label="{{ i18n "commons.menu.main" }}">
     <div class="container">
       {{ partial "header/logo.html" }}
       {{ if $primary.items }}
diff --git a/layouts/partials/header/search.html b/layouts/partials/header/search.html
deleted file mode 100644
index 0bfa966a..00000000
--- a/layouts/partials/header/search.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{{ $search_appareance := site.Params.search.appearance }}
-{{ $search_position := site.Params.search.position }}
-
-<button id="search-button" class="pagefind-ui__toggle pagefind-{{ .position }} toggle-{{ $search_appareance }}" aria-expanded="false" aria-label='{{- i18n (printf "commons.search.title") -}}'>
-  <span>{{- i18n (printf "commons.search.title") -}}</span>
-</button>
-
-<script src="/pagefind/pagefind-ui.js"></script>
-
-<div id="search" class="search__modal" aria-hidden="true" aria-modal="true" role="dialog" aria-label="{{ i18n "commons.search.label" }}">
-  <button class="search__close" aria-label="{{ i18n "commons.search.close" }}">
-    {{ i18n "commons.search.close" }}
-  </button>
-  <p role="heading" aria-level="1" class="sr-only">{{ i18n "commons.search.title" }}</p>
-</div>
\ No newline at end of file
-- 
GitLab