Files
nfel 32e7b6b749
CI/CD Dev / dev (push) Failing after 44s
feat: add persistent dashboard dark mode
2026-08-15 00:53:58 +03:30

55 lines
1.8 KiB
JavaScript

(() => {
const storageKey = "gl-theme";
const root = document.documentElement;
const storedTheme = () => {
try {
const value = localStorage.getItem(storageKey);
return value === "dark" || value === "light" ? value : "";
} catch (_) {
return "";
}
};
const systemTheme = () =>
window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
const updateControls = (theme) => {
document.querySelectorAll("[data-theme-toggle]").forEach((control) => {
const dark = theme === "dark";
control.setAttribute("aria-pressed", String(dark));
control.setAttribute("aria-label", dark ? control.dataset.lightLabel : control.dataset.darkLabel);
const icon = control.querySelector("[data-theme-icon]");
if (icon) icon.textContent = dark ? "☀" : "☾";
});
};
const applyTheme = (theme) => {
root.dataset.theme = theme;
root.style.colorScheme = theme;
updateControls(theme);
};
applyTheme(storedTheme() || systemTheme());
document.addEventListener("DOMContentLoaded", () => updateControls(root.dataset.theme));
document.addEventListener("htmx:afterSwap", () => updateControls(root.dataset.theme));
document.addEventListener("click", (event) => {
if (!(event.target instanceof Element)) return;
const control = event.target.closest("[data-theme-toggle]");
if (!control) return;
const theme = root.dataset.theme === "dark" ? "light" : "dark";
try {
localStorage.setItem(storageKey, theme);
} catch (_) {
// The selected theme still applies for this page when storage is unavailable.
}
applyTheme(theme);
});
const media = window.matchMedia("(prefers-color-scheme: dark)");
media.addEventListener?.("change", () => {
if (!storedTheme()) applyTheme(systemTheme());
});
})();