From e56020d086cad091637733185786c86adf0d1287 Mon Sep 17 00:00:00 2001 From: Kosztyk <36381705+Kosztyk@users.noreply.github.com> Date: Mon, 12 Jan 2026 22:06:43 +0200 Subject: [PATCH] Update theme.js --- public/theme.js | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/public/theme.js b/public/theme.js index 8923457..8a7d0ce 100644 --- a/public/theme.js +++ b/public/theme.js @@ -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 root = document.documentElement; - const mql = window.matchMedia?.("(prefers-color-scheme: dark)"); const getStoredTheme = () => { @@ -23,14 +15,16 @@ 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 }) => { if (theme !== "dark" && theme !== "light") return; root.setAttribute("data-theme", theme); - // Hint to the browser for built-in UI (form controls, scrollbars, etc.) - root.style.colorScheme = theme; + applyColorSchemeOnly(theme); if (persist) { try { @@ -43,28 +37,27 @@ const clearThemeOverride = () => { root.removeAttribute("data-theme"); - root.style.colorScheme = ""; try { localStorage.removeItem(KEY); } catch { // ignore } + // Important: even in auto-mode we still set color-scheme to system theme. + applyColorSchemeOnly(getSystemTheme()); }; + const getEffectiveTheme = () => getStoredTheme() ?? getSystemTheme(); + const syncUI = () => { const checkbox = document.getElementById("cx-theme-switch"); const label = document.getElementById("cx-theme-label"); - if (!checkbox && !label) return; const theme = getEffectiveTheme(); if (checkbox) { checkbox.checked = theme === "dark"; - checkbox.setAttribute( - "aria-checked", - checkbox.checked ? "true" : "false", - ); + checkbox.setAttribute("aria-checked", checkbox.checked ? "true" : "false"); } if (label) { @@ -73,13 +66,16 @@ }; // --- Initial state --- - // If the user chose a theme before, enforce it. const stored = getStoredTheme(); + if (stored) { + // Explicit override: lock both tokens + native controls. 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", () => { syncUI(); @@ -87,21 +83,22 @@ if (!checkbox) return; checkbox.addEventListener("change", () => { - // Explicit user choice always overrides system. setTheme(checkbox.checked ? "dark" : "light", { persist: true }); syncUI(); }); }); - // If there's no explicit override, reflect OS changes in the UI. + if (mql) { const onChange = () => { if (getStoredTheme() == null) { - clearThemeOverride(); + // Keep auto: no data-theme, but update color-scheme + UI. + root.removeAttribute("data-theme"); + applyColorSchemeOnly(getSystemTheme()); syncUI(); } }; - // Safari uses addListener/removeListener + if (typeof mql.addEventListener === "function") { mql.addEventListener("change", onChange); } else if (typeof mql.addListener === "function") {