From 2721682fc29dc94fa8c41978866c174d216cc83e Mon Sep 17 00:00:00 2001 From: Vitalii Perehonchuk Date: Wed, 4 Sep 2024 15:15:50 +0300 Subject: [PATCH] fix: dark mode --- components/toggleDarkMode.tsx | 51 ++++++++++++++++++++++------------- pages/_document.tsx | 6 +++++ utils/apply-dark-mode.ts | 18 +++++++++++++ 3 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 utils/apply-dark-mode.ts diff --git a/components/toggleDarkMode.tsx b/components/toggleDarkMode.tsx index 83d4828..9f16d13 100755 --- a/components/toggleDarkMode.tsx +++ b/components/toggleDarkMode.tsx @@ -1,27 +1,42 @@ -import { useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; + import { MoonIcon, SunIcon } from './icons'; + export const LIGHTS_OUT = 'lights-out'; export default function ToggleDarkMode({ className }: { className?: string }) { - const [isDarkMode, setDarkMode] = useState(false); - - const handleClick = () => { - const hasDarkMode = document.documentElement.hasAttribute(LIGHTS_OUT); - - return toggleDarkMode(!hasDarkMode); - }; - - const toggleDarkMode = (shouldBeDark) => { - document.documentElement.toggleAttribute(LIGHTS_OUT, shouldBeDark); - - setDarkMode(shouldBeDark); + const [isDarkMode, setIsDarkMode] = useState( + globalThis.localStorage && + globalThis.localStorage.getItem(LIGHTS_OUT) === 'true' + ); + useEffect(() => { + const mq = window.matchMedia('(prefers-color-scheme: dark)'); - writeToStorage(shouldBeDark); - }; + if (mq.matches) { + setIsDarkMode(true); + } - const writeToStorage = (prefersDark) => { - localStorage.setItem(LIGHTS_OUT, prefersDark ? 'true' : 'false'); - }; + // This callback will fire if the preferred color scheme changes without a reload + mq.addEventListener('change', (evt) => setIsDarkMode(evt.matches)); + }, []); + useEffect(() => { + console.log('isDarkMode changed!', isDarkMode); + if (isDarkMode) { + globalThis.document.documentElement.dataset.theme = 'dark'; + } else { + globalThis.document.documentElement.dataset.theme = null; + } + }, [isDarkMode]); + const handleClick = useCallback(() => { + setIsDarkMode((wasDarkMode) => { + if (wasDarkMode) { + globalThis.localStorage.removeItem(LIGHTS_OUT); + } else { + globalThis.localStorage.setItem(LIGHTS_OUT, 'true'); + } + return !wasDarkMode; + }); + }, []); return (