-
-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathuseDarkMode.ts
More file actions
57 lines (46 loc) · 1.75 KB
/
Copy pathuseDarkMode.ts
File metadata and controls
57 lines (46 loc) · 1.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { useCallback, useEffect, useState } from "react";
/**
* Custom hook for detecting and managing dark mode state
* Handles system preferences, local storage, and class/attribute changes
*/
export function useDarkMode() {
const [isDarkMode, setIsDarkMode] = useState(false);
const [mounted, setMounted] = useState(false);
// Optimized theme detection
const checkDarkMode = useCallback(() => {
if (typeof window === "undefined") return;
const hasDarkClass = document.documentElement.classList.contains("dark");
const dataTheme = document.documentElement.getAttribute("data-theme");
const systemPrefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
const savedTheme = localStorage.getItem("theme");
const isDark =
savedTheme === "dark" ||
dataTheme === "dark" ||
hasDarkClass ||
(savedTheme !== "light" && dataTheme !== "light" && systemPrefersDark);
setIsDarkMode(isDark);
}, []);
useEffect(() => {
setMounted(true);
checkDarkMode();
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", checkDarkMode);
const observer = new MutationObserver(checkDarkMode);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class", "data-theme"],
});
const handleStorageChange = (e: StorageEvent) => {
if (e.key === "theme") checkDarkMode();
};
window.addEventListener("storage", handleStorageChange);
return () => {
mediaQuery.removeEventListener("change", checkDarkMode);
observer.disconnect();
window.removeEventListener("storage", handleStorageChange);
};
}, [checkDarkMode]);
return { isDarkMode, mounted };
}