save theme preference to localStorage

This commit is contained in:
Nathaniel Tampus
2023-04-09 14:03:04 +08:00
parent 8940a1bf3b
commit 6d2263432a
2 changed files with 30 additions and 16 deletions

View File

@@ -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>
); );

View File

@@ -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" />