Add files via upload

This commit is contained in:
Kosztyk 2026-01-12 21:11:03 +02:00 committed by GitHub
parent f0c90f2c3b
commit ad4d365d7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

111
public/theme.js Normal file
View file

@ -0,0 +1,111 @@
/*
* 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 = () => {
try {
const v = localStorage.getItem(KEY);
return v === "dark" || v === "light" ? v : null;
} catch {
return null;
}
};
const getSystemTheme = () => (mql && mql.matches ? "dark" : "light");
const getEffectiveTheme = () => getStoredTheme() ?? getSystemTheme();
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;
if (persist) {
try {
localStorage.setItem(KEY, theme);
} catch {
// ignore
}
}
};
const clearThemeOverride = () => {
root.removeAttribute("data-theme");
root.style.colorScheme = "";
try {
localStorage.removeItem(KEY);
} catch {
// ignore
}
};
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",
);
}
if (label) {
label.textContent = theme === "dark" ? "Dark" : "Light";
}
};
// --- Initial state ---
// If the user chose a theme before, enforce it.
const stored = getStoredTheme();
if (stored) {
setTheme(stored, { persist: false });
}
// Keep the toggle in sync once the DOM is available.
document.addEventListener("DOMContentLoaded", () => {
syncUI();
const checkbox = document.getElementById("cx-theme-switch");
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();
syncUI();
}
};
// Safari uses addListener/removeListener
if (typeof mql.addEventListener === "function") {
mql.addEventListener("change", onChange);
} else if (typeof mql.addListener === "function") {
mql.addListener(onChange);
}
}
})();