yak(theme-explicit-light-is-overridden-on-dark-os-browsers-chip-backgrounds-are-dropped-pku7): theme: explicit light is overridden on dark-OS browsers; chip backgrounds are dropped

This commit is contained in:
Willem van den Ende
2026-10-29 13:07:08 +00:00
parent edba66239e
commit f5faa8a3af
4 changed files with 248 additions and 26 deletions
@@ -14,20 +14,37 @@
</script>
<script>
(() => {
const setTheme = (theme) => {
if (theme === "system") {
localStorage.removeItem("phx:theme");
document.documentElement.removeAttribute("data-theme");
} else {
localStorage.setItem("phx:theme", theme);
document.documentElement.setAttribute("data-theme", theme);
}
// Theme selection is always explicit: the document always carries a
// data-theme attribute, resolved here before first paint. An explicit
// choice therefore always wins in CSS, whatever the OS preference is;
// no stylesheet rule follows the OS on its own.
//
// data-theme-choice records what the visitor actually chose (unset,
// system, light, dark) and is what the toggle's knob follows: in
// "system" mode the palette may resolve to light or dark, but the
// system icon must stay selected.
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
const stored = () => localStorage.getItem("phx:theme");
const resolve = (theme) =>
theme === "system" ? (prefersDark.matches ? "dark" : "light") : theme;
const apply = (theme) => {
document.documentElement.setAttribute("data-theme", resolve(theme));
document.documentElement.setAttribute("data-theme-choice", theme);
};
const setTheme = (theme) => {
localStorage.setItem("phx:theme", theme);
apply(theme);
};
// Light is the default: no stored preference means light, not "follow
// the OS". "System" is an explicit choice and is stored as such.
if (!document.documentElement.hasAttribute("data-theme")) {
setTheme(localStorage.getItem("phx:theme") || "system");
apply(stored() || "light");
}
window.addEventListener("storage", (e) => e.key === "phx:theme" && setTheme(e.newValue || "system"));
// Follow the OS only while the visitor's recorded choice is "system".
prefersDark.addEventListener("change", () => {
if (stored() === "system") apply("system");
});
window.addEventListener("storage", (e) => e.key === "phx:theme" && setTheme(e.newValue || "light"));
window.addEventListener("phx:set-theme", (e) => setTheme(e.target.dataset.phxTheme));
})();
</script>