From e2a1ac011363b9dc60ccbf8a45325771c7a5f750 Mon Sep 17 00:00:00 2001 From: bunker-admin Date: Mon, 9 Mar 2026 15:55:01 -0600 Subject: [PATCH] Fix MkDocs search not displaying results with custom header The collapsed Material header (height: 0, overflow: visible) left the search input reachable but the __search checkbox was never toggled when users typed directly into it. This prevented both Material's native CSS and our custom CSS from revealing the results panel (opacity stayed 0, scrollwrap max-height stayed 0). - Add focusin/input event delegation to check __search on direct input - Add search icon, dark mode toggle, and docs sidebar toggle to header - Add CSS for hidden Material header, search positioning, palette, tabs - Avoid Jinja2 block syntax inside JS comments (parsed as directives) Bunker Admin --- mkdocs/docs/overrides/main.html | 229 ++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) diff --git a/mkdocs/docs/overrides/main.html b/mkdocs/docs/overrides/main.html index 14471db0..690b8f0c 100644 --- a/mkdocs/docs/overrides/main.html +++ b/mkdocs/docs/overrides/main.html @@ -43,6 +43,12 @@ descriptionPages languageWebsite menu_bookDocs + + login Sign In @@ -106,6 +112,20 @@ descriptionPages languageWebsite menu_bookDocs +
+ + + +
login Sign In @@ -209,6 +229,96 @@ } }); document.body.appendChild(iframe); + // Palette toggle (dark/light mode) + function togglePalette() { + var inputs = document.querySelectorAll('.cm-palette-container input[name="__palette"]'); + for (var i = 0; i < inputs.length; i++) { + if (!inputs[i].checked) { inputs[i].click(); break; } + } + setTimeout(updatePaletteIcon, 50); + } + function updatePaletteIcon() { + var scheme = document.body.getAttribute('data-md-color-scheme') || 'default'; + var isDark = scheme === 'slate'; + var icon = isDark ? 'light_mode' : 'dark_mode'; + document.querySelectorAll('#cm-palette-toggle .material-icons-outlined, #cm-mobile-palette-toggle .material-icons-outlined').forEach(function(el) { + el.textContent = icon; + }); + var ml = document.querySelector('#cm-mobile-palette-toggle span:not(.material-icons-outlined)'); + if (ml) ml.textContent = isDark ? 'Light Mode' : 'Dark Mode'; + } + var ptBtn = document.getElementById('cm-palette-toggle'); + var ptBtnM = document.getElementById('cm-mobile-palette-toggle'); + if (ptBtn) ptBtn.addEventListener('click', togglePalette); + if (ptBtnM) ptBtnM.addEventListener('click', function() { togglePalette(); closeDrawer(); }); + // Docs sidebar toggle (opens Material's docs navigation drawer) + var docsSidebarBtn = document.getElementById('cm-docs-sidebar-toggle'); + if (docsSidebarBtn) { + docsSidebarBtn.addEventListener('click', function() { + closeDrawer(); + var dt = document.getElementById('__drawer'); + if (dt) { dt.checked = !dt.checked; dt.dispatchEvent(new Event('change')); } + }); + } + // Close custom drawer when search label is clicked on mobile + auto-focus input + document.querySelectorAll('label[for="__search"]').forEach(function(el) { + el.addEventListener('click', function() { + closeDrawer(); + setTimeout(function() { + var input = document.querySelector('.md-search__input'); + if (input) input.focus(); + }, 150); + }); + }); + // Search activation: mirror checkbox state as a body class for CSS targeting. + // On desktop, Material's search input is always visible (overflow from collapsed + // header). Typing directly into it triggers the search worker but never checks + // the __search checkbox, so the results panel stays hidden. We fix this by + // checking the checkbox on input focus/input events. + var searchToggle = document.getElementById('__search'); + if (searchToggle) { + function syncSearchClass() { + document.body.classList.toggle('cm-search-active', searchToggle.checked); + } + searchToggle.addEventListener('change', syncSearchClass); + syncSearchClass(); + // Activate search when the Material input is focused or typed into directly. + // Uses event delegation because the search input is rendered after this + // script (announce block runs before header block). + document.addEventListener('focusin', function(e) { + if (e.target && e.target.classList && e.target.classList.contains('md-search__input')) { + if (!searchToggle.checked) { + searchToggle.checked = true; + searchToggle.dispatchEvent(new Event('change')); + } + } + }); + document.addEventListener('input', function(e) { + if (e.target && e.target.classList && e.target.classList.contains('md-search__input')) { + if (!searchToggle.checked) { + searchToggle.checked = true; + searchToggle.dispatchEvent(new Event('change')); + } + } + }); + // Click-outside to dismiss search + document.addEventListener('click', function(e) { + if (!searchToggle.checked) return; + var panel = document.querySelector('.md-search__inner'); + if (panel && panel.contains(e.target)) return; + if (e.target.closest && e.target.closest('label[for="__search"]')) return; + searchToggle.checked = false; + syncSearchClass(); + }); + // Also sync on Escape key (Material toggles checkbox via JS) + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape') setTimeout(syncSearchClass, 50); + }); + } + // Init palette icon + observe changes + setTimeout(updatePaletteIcon, 100); + new MutationObserver(function() { updatePaletteIcon(); }) + .observe(document.body, { attributes: true, attributeFilter: ['data-md-color-scheme'] }); })(); {% endblock %} + +{% block header %} +
+
+ {% if config.theme.palette %} + {% if not config.theme.palette is mapping %} + {% include "partials/palette.html" %} + {% endif %} + {% endif %} +
+ {% if "material/search" in config.plugins %} + {% include "partials/search.html" %} + {% endif %} +
+{% endblock %} + +{% block tabs %}{% endblock %}