From 8042116a69bec2c0c0c4a997290166bd54236de9 Mon Sep 17 00:00:00 2001 From: fen Date: Thu, 10 Sep 2026 12:10:00 -0500 Subject: [PATCH] Fix settings dark mode toggle double-binding and center it (#197) topbar.js binds click handlers to every .dark-toggle, including the settings one; settings.js then also wired a delegation that re-clicked the topbar button, so each click flipped dark mode twice (net no-op). Mark buttons as wired in topbar.js and only add a fallback handler in settings.js when topbar.js did not run. CSS: center the toggle horizontally under the Settings title with auto margins, matching .settings-body padding. Closes #197 --- internal/web/static/app.css | 8 +++++++- internal/web/static/settings.js | 14 +++++++++----- internal/web/static/topbar.js | 3 +++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/web/static/app.css b/internal/web/static/app.css index 463e78a..0e13741 100644 --- a/internal/web/static/app.css +++ b/internal/web/static/app.css @@ -255,7 +255,13 @@ body { .theme-grid { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; } /* #161: more breathing room between settings sections */ -#settings-dark-toggle { margin-bottom: 20px; } +#settings-dark-toggle { + margin-bottom: 20px; + margin-left: auto; + margin-right: auto; + display: flex; + justify-content: center; +} .settings-body h3 { margin-top: 28px; } .settings-body .theme-grid { margin-bottom: 8px; } .theme-card { diff --git a/internal/web/static/settings.js b/internal/web/static/settings.js index 58900b7..961ff83 100644 --- a/internal/web/static/settings.js +++ b/internal/web/static/settings.js @@ -91,11 +91,15 @@ if (dt) dt.setAttribute('aria-pressed', s.dark ? 'true' : 'false'); } sync(); - // the topbar script runs before this button exists, so wire it here + // topbar.js already binds every .dark-toggle (deferred, so the settings + // button exists by then). Only wire here if it somehow did not run, + // otherwise the button would toggle twice per click and never change (#197). var dt = document.getElementById('settings-dark-toggle'); - dt.addEventListener('click', function () { - var btns = document.querySelectorAll('.topbar .dark-toggle'); - if (btns.length) btns[0].click(); else document.dispatchEvent(new CustomEvent('palette-darkchange')); - }); + if (dt && !dt.dataset.darkWired) { + dt.addEventListener('click', function () { + var btns = document.querySelectorAll('.topbar .dark-toggle'); + if (btns.length) btns[0].click(); else document.dispatchEvent(new CustomEvent('palette-darkchange')); + }); + } document.addEventListener('palette-darkchange', sync); })(); diff --git a/internal/web/static/topbar.js b/internal/web/static/topbar.js index 8a6989f..e2c98ca 100644 --- a/internal/web/static/topbar.js +++ b/internal/web/static/topbar.js @@ -31,6 +31,9 @@ apply(); sync(Array.prototype.slice.call(btns)); btns.forEach(function (b) { + // mark as wired so settings.js does not add a second handler + // (#197: double-binding made the settings toggle flip twice = no-op) + b.dataset.darkWired = '1'; b.addEventListener('click', function () { var s = state(); var dark = !s.dark;