save theme preference to localStorage
This commit is contained in:
@@ -48,6 +48,19 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|||||||
</ContextProvider>
|
</ContextProvider>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
||||||
|
{/* not using <Script> from next/script since it executes too late */}
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
id="load-theme"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `if (localStorage.theme === "dark" || (!("theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
||||||
|
document.documentElement.setAttribute("data-theme", "chessuDark");
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute("data-theme", "chessuLight");
|
||||||
|
}`
|
||||||
|
}}
|
||||||
|
></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,31 +7,32 @@ export default function ThemeToggle() {
|
|||||||
const [darkTheme, setDarkTheme] = useState(false);
|
const [darkTheme, setDarkTheme] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onChange = (e: MediaQueryListEvent) => changeTheme(e.matches ? "dark" : "light");
|
if (document.documentElement.getAttribute("data-theme") === "chessuDark") {
|
||||||
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", onChange);
|
|
||||||
|
|
||||||
changeTheme(window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", onChange);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function changeTheme(theme: "dark" | "light") {
|
|
||||||
if (theme === "dark") {
|
|
||||||
document.documentElement.setAttribute("data-theme", "chessuDark");
|
|
||||||
setDarkTheme(true);
|
setDarkTheme(true);
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.setAttribute("data-theme", "chessuLight");
|
|
||||||
setDarkTheme(false);
|
setDarkTheme(false);
|
||||||
}
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function toggleTheme() {
|
||||||
|
if (
|
||||||
|
document.documentElement.getAttribute("data-theme") === "chessuDark" ||
|
||||||
|
(!("theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||||
|
) {
|
||||||
|
document.documentElement.setAttribute("data-theme", "chessuLight");
|
||||||
|
localStorage.theme = "light";
|
||||||
|
setDarkTheme(false);
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute("data-theme", "chessuDark");
|
||||||
|
localStorage.theme = "dark";
|
||||||
|
setDarkTheme(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Toggle theme"
|
aria-label="Toggle theme"
|
||||||
onClick={() => changeTheme(darkTheme ? "light" : "dark")}
|
onClick={toggleTheme}
|
||||||
className={"btn btn-ghost btn-circle swap swap-rotate" + (darkTheme ? " swap-active" : "")}
|
className={"btn btn-ghost btn-circle swap swap-rotate" + (darkTheme ? " swap-active" : "")}
|
||||||
>
|
>
|
||||||
<IconSun className="swap-on m-auto block h-full" />
|
<IconSun className="swap-on m-auto block h-full" />
|
||||||
|
|||||||
Reference in New Issue
Block a user