feat: fix light dark mode issue
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
3491b4b1ba
commit
cbed65de66
4 changed files with 66 additions and 25 deletions
|
|
@ -15,20 +15,56 @@
|
|||
</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);
|
||||
}
|
||||
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const systemTheme = () => (mq.matches ? "dark" : "light");
|
||||
|
||||
// Single source of truth:
|
||||
// - localStorage["phx:theme"] = "light" | "dark" (explicit override)
|
||||
// - missing key => "system"
|
||||
const storedTheme = () => localStorage.getItem("phx:theme") || "system";
|
||||
|
||||
const effectiveTheme = (t) => (t === "system" ? systemTheme() : t);
|
||||
|
||||
const applyThemeNow = (t) => {
|
||||
document.documentElement.setAttribute("data-theme", effectiveTheme(t));
|
||||
};
|
||||
if (!document.documentElement.hasAttribute("data-theme")) {
|
||||
setTheme(localStorage.getItem("phx:theme") || "system");
|
||||
}
|
||||
window.addEventListener("storage", (e) => e.key === "phx:theme" && setTheme(e.newValue || "system"));
|
||||
|
||||
const syncToggle = () => {
|
||||
const eff = effectiveTheme(storedTheme());
|
||||
document.querySelectorAll("[data-theme-toggle]").forEach((el) => {
|
||||
el.checked = eff === "dark";
|
||||
});
|
||||
};
|
||||
|
||||
const setTheme = (t) => {
|
||||
if (t === "system") localStorage.removeItem("phx:theme");
|
||||
else localStorage.setItem("phx:theme", t);
|
||||
|
||||
applyThemeNow(t);
|
||||
syncToggle(); // if toggle exists already
|
||||
};
|
||||
|
||||
// 1) Apply theme ASAP to match system on first paint
|
||||
applyThemeNow(storedTheme());
|
||||
|
||||
// 2) Sync toggle once DOM is ready (fixes initial "light" toggle)
|
||||
document.addEventListener("DOMContentLoaded", syncToggle);
|
||||
|
||||
// 3) If toggle appears later (LiveView render), sync immediately
|
||||
const obs = new MutationObserver(() => {
|
||||
if (document.querySelector("[data-theme-toggle]")) syncToggle();
|
||||
});
|
||||
obs.observe(document.documentElement, { childList: true, subtree: true });
|
||||
|
||||
window.addEventListener("phx:set-theme", ({ detail: { theme } }) => setTheme(theme));
|
||||
window.addEventListener("storage", (e) => e.key === "phx:theme" && setTheme(e.newValue || "system"));
|
||||
|
||||
mq.addEventListener("change", () => {
|
||||
if (localStorage.getItem("phx:theme") === null) {
|
||||
applyThemeNow("system");
|
||||
syncToggle();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -248,12 +248,17 @@ defmodule MvWeb.Layouts.Sidebar do
|
|||
aria-label={gettext("Toggle dark mode")}
|
||||
>
|
||||
<.icon name="hero-sun" class="size-5" aria-hidden="true" />
|
||||
<input
|
||||
type="checkbox"
|
||||
value="dark"
|
||||
class="toggle toggle-sm theme-controller focus:outline-none"
|
||||
aria-label={gettext("Toggle dark mode")}
|
||||
/>
|
||||
<div id="theme-toggle" phx-update="ignore">
|
||||
<input
|
||||
id="theme-toggle-input"
|
||||
type="checkbox"
|
||||
class="toggle toggle-sm focus:outline-none"
|
||||
data-theme-toggle
|
||||
onchange="window.dispatchEvent(new CustomEvent('phx:set-theme',{detail:{theme:this.checked?'dark':'light'}}))"
|
||||
aria-label={gettext("Toggle dark mode")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<.icon name="hero-moon" class="size-5" aria-hidden="true" />
|
||||
</label>
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue