Update theme.js

This commit is contained in:
Kosztyk 2026-01-12 22:06:43 +02:00 committed by GitHub
parent f71ebd5d98
commit e56020d086
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,15 +1,7 @@
/*
* ConvertX Theme Toggle
*
* - Stores explicit user choice in localStorage under KEY.
* - If no explicit choice exists, the UI follows the OS preference
* (prefers-color-scheme) and does not set data-theme.
*/
(() => { (() => {
const KEY = "convertx-theme"; const KEY = "convertx-theme";
const root = document.documentElement; const root = document.documentElement;
const mql = window.matchMedia?.("(prefers-color-scheme: dark)"); const mql = window.matchMedia?.("(prefers-color-scheme: dark)");
const getStoredTheme = () => { const getStoredTheme = () => {
@ -23,14 +15,16 @@
const getSystemTheme = () => (mql && mql.matches ? "dark" : "light"); const getSystemTheme = () => (mql && mql.matches ? "dark" : "light");
const getEffectiveTheme = () => getStoredTheme() ?? getSystemTheme(); const applyColorSchemeOnly = (theme) => {
// Hint to the browser for built-in UI (form controls, scrollbars, etc.)
root.style.colorScheme = theme === "dark" ? "dark" : "light";
};
const setTheme = (theme, { persist } = { persist: true }) => { const setTheme = (theme, { persist } = { persist: true }) => {
if (theme !== "dark" && theme !== "light") return; if (theme !== "dark" && theme !== "light") return;
root.setAttribute("data-theme", theme); root.setAttribute("data-theme", theme);
// Hint to the browser for built-in UI (form controls, scrollbars, etc.) applyColorSchemeOnly(theme);
root.style.colorScheme = theme;
if (persist) { if (persist) {
try { try {
@ -43,28 +37,27 @@
const clearThemeOverride = () => { const clearThemeOverride = () => {
root.removeAttribute("data-theme"); root.removeAttribute("data-theme");
root.style.colorScheme = "";
try { try {
localStorage.removeItem(KEY); localStorage.removeItem(KEY);
} catch { } catch {
// ignore // ignore
} }
// Important: even in auto-mode we still set color-scheme to system theme.
applyColorSchemeOnly(getSystemTheme());
}; };
const getEffectiveTheme = () => getStoredTheme() ?? getSystemTheme();
const syncUI = () => { const syncUI = () => {
const checkbox = document.getElementById("cx-theme-switch"); const checkbox = document.getElementById("cx-theme-switch");
const label = document.getElementById("cx-theme-label"); const label = document.getElementById("cx-theme-label");
if (!checkbox && !label) return; if (!checkbox && !label) return;
const theme = getEffectiveTheme(); const theme = getEffectiveTheme();
if (checkbox) { if (checkbox) {
checkbox.checked = theme === "dark"; checkbox.checked = theme === "dark";
checkbox.setAttribute( checkbox.setAttribute("aria-checked", checkbox.checked ? "true" : "false");
"aria-checked",
checkbox.checked ? "true" : "false",
);
} }
if (label) { if (label) {
@ -73,13 +66,16 @@
}; };
// --- Initial state --- // --- Initial state ---
// If the user chose a theme before, enforce it.
const stored = getStoredTheme(); const stored = getStoredTheme();
if (stored) { if (stored) {
// Explicit override: lock both tokens + native controls.
setTheme(stored, { persist: false }); setTheme(stored, { persist: false });
} else {
// Auto mode: follow OS, but ensure native controls match.
applyColorSchemeOnly(getSystemTheme());
} }
// Keep the toggle in sync once the DOM is available.
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
syncUI(); syncUI();
@ -87,21 +83,22 @@
if (!checkbox) return; if (!checkbox) return;
checkbox.addEventListener("change", () => { checkbox.addEventListener("change", () => {
// Explicit user choice always overrides system.
setTheme(checkbox.checked ? "dark" : "light", { persist: true }); setTheme(checkbox.checked ? "dark" : "light", { persist: true });
syncUI(); syncUI();
}); });
}); });
// If there's no explicit override, reflect OS changes in the UI.
if (mql) { if (mql) {
const onChange = () => { const onChange = () => {
if (getStoredTheme() == null) { if (getStoredTheme() == null) {
clearThemeOverride(); // Keep auto: no data-theme, but update color-scheme + UI.
root.removeAttribute("data-theme");
applyColorSchemeOnly(getSystemTheme());
syncUI(); syncUI();
} }
}; };
// Safari uses addListener/removeListener
if (typeof mql.addEventListener === "function") { if (typeof mql.addEventListener === "function") {
mql.addEventListener("change", onChange); mql.addEventListener("change", onChange);
} else if (typeof mql.addListener === "function") { } else if (typeof mql.addListener === "function") {