Fix settings dark mode toggle double-binding and center it (#197)
CI / test (pull_request) Successful in 50s
CI / docker (pull_request) Skipped

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
This commit is contained in:
fen
2026-09-10 12:10:00 -05:00
parent b603b29359
commit 8042116a69
3 changed files with 19 additions and 6 deletions
+7 -1
View File
@@ -255,7 +255,13 @@ body {
.theme-grid { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; } .theme-grid { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px; }
/* #161: more breathing room between settings sections */ /* #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 h3 { margin-top: 28px; }
.settings-body .theme-grid { margin-bottom: 8px; } .settings-body .theme-grid { margin-bottom: 8px; }
.theme-card { .theme-card {
+5 -1
View File
@@ -91,11 +91,15 @@
if (dt) dt.setAttribute('aria-pressed', s.dark ? 'true' : 'false'); if (dt) dt.setAttribute('aria-pressed', s.dark ? 'true' : 'false');
} }
sync(); 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'); var dt = document.getElementById('settings-dark-toggle');
if (dt && !dt.dataset.darkWired) {
dt.addEventListener('click', function () { dt.addEventListener('click', function () {
var btns = document.querySelectorAll('.topbar .dark-toggle'); var btns = document.querySelectorAll('.topbar .dark-toggle');
if (btns.length) btns[0].click(); else document.dispatchEvent(new CustomEvent('palette-darkchange')); if (btns.length) btns[0].click(); else document.dispatchEvent(new CustomEvent('palette-darkchange'));
}); });
}
document.addEventListener('palette-darkchange', sync); document.addEventListener('palette-darkchange', sync);
})(); })();
+3
View File
@@ -31,6 +31,9 @@
apply(); apply();
sync(Array.prototype.slice.call(btns)); sync(Array.prototype.slice.call(btns));
btns.forEach(function (b) { 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 () { b.addEventListener('click', function () {
var s = state(); var s = state();
var dark = !s.dark; var dark = !s.dark;