From 940559b48048254799f66c53afdc25db0c16887a Mon Sep 17 00:00:00 2001 From: Marco Pisco Date: Sat, 23 May 2026 22:39:29 +0000 Subject: [PATCH 1/2] fix(admin): defer navbar theme application to DOMContentLoaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit theme-switcher.js ran in before #admin-navbar existed in the DOM, so the initial navbar class switch (navbar-dark/bg-dark ↔ navbar-light/bg-light) silently failed. Only the MatchMedia change listener worked — meaning the navbar only got correct classes after a live OS theme toggle, never on initial page load. Split into: set data-bs-theme immediately (avoids flash), apply navbar classes deferred via DOMContentLoaded, and the change listener now calls the unified applyTheme() for both. --- assets/theme-switcher.js | 48 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/assets/theme-switcher.js b/assets/theme-switcher.js index f410f56..4c30b33 100644 --- a/assets/theme-switcher.js +++ b/assets/theme-switcher.js @@ -2,29 +2,39 @@ (function() { const htmlElement = document.documentElement; const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)'); - - // Function to apply theme - function applyTheme(isDark) { - htmlElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light'); - - // Handle admin navbar specifically + + // Set data-bs-theme immediately (before DOM is ready) to avoid flash of wrong theme + htmlElement.setAttribute('data-bs-theme', darkModeQuery.matches ? 'dark' : 'light'); + + // Handle admin navbar — deferred until DOM is ready so #admin-navbar exists + function applyNavbarTheme(isDark) { const adminNavbar = document.getElementById('admin-navbar'); - if (adminNavbar) { - if (isDark) { - adminNavbar.classList.remove('navbar-light', 'bg-light'); - adminNavbar.classList.add('navbar-dark', 'bg-dark'); - } else { - adminNavbar.classList.remove('navbar-dark', 'bg-dark'); - adminNavbar.classList.add('navbar-light', 'bg-light'); - } + if (!adminNavbar) return; + if (isDark) { + adminNavbar.classList.remove('navbar-light', 'bg-light'); + adminNavbar.classList.add('navbar-dark', 'bg-dark'); + } else { + adminNavbar.classList.remove('navbar-dark', 'bg-dark'); + adminNavbar.classList.add('navbar-light', 'bg-light'); } } - - // Set initial theme based on system preference - applyTheme(darkModeQuery.matches); - + + function applyTheme(isDark) { + htmlElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light'); + applyNavbarTheme(isDark); + } + + // Apply navbar classes once the DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', function () { + applyNavbarTheme(darkModeQuery.matches); + }); + } else { + applyNavbarTheme(darkModeQuery.matches); + } + // Listen for changes in system theme preference - darkModeQuery.addEventListener('change', e => { + darkModeQuery.addEventListener('change', function (e) { applyTheme(e.matches); }); })(); From 450a00d2ac6ee8554fe413b60165019f2e5523b2 Mon Sep 17 00:00:00 2001 From: Marco Pisco Date: Sat, 23 May 2026 22:45:41 +0000 Subject: [PATCH 2/2] fix(admin): eliminate navbar theme flash on page load Expose window.__applyNavbarTheme from theme-switcher.js and call it via an inline
"; $csrfTokenHtml = htmlspecialchars(generate_csrf_token(), ENT_QUOTES, 'UTF-8'); echo ""; diff --git a/assets/theme-switcher.js b/assets/theme-switcher.js index 4c30b33..972d7fa 100644 --- a/assets/theme-switcher.js +++ b/assets/theme-switcher.js @@ -6,7 +6,7 @@ // Set data-bs-theme immediately (before DOM is ready) to avoid flash of wrong theme htmlElement.setAttribute('data-bs-theme', darkModeQuery.matches ? 'dark' : 'light'); - // Handle admin navbar — deferred until DOM is ready so #admin-navbar exists + // Handle admin navbar class switching function applyNavbarTheme(isDark) { const adminNavbar = document.getElementById('admin-navbar'); if (!adminNavbar) return; @@ -19,21 +19,26 @@ } } - function applyTheme(isDark) { - htmlElement.setAttribute('data-bs-theme', isDark ? 'dark' : 'light'); - applyNavbarTheme(isDark); - } + // Exposed for inline