-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdarkMode.tsx
73 lines (60 loc) · 1.85 KB
/
darkMode.tsx
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React, {useState, useEffect, useCallback, useContext} from 'react';
const preferDarkQuery = '(prefers-color-scheme: dark)';
const DarkModeContext = React.createContext(false);
const DarkModeActionContext = React.createContext({
setMode: (p: boolean) => {},
toggle: () => {},
});
type ProviderProps = {
storageKey?: string;
classNameDark?: string;
classNameLight?: string;
children: React.ReactNode;
};
type Listener = (p: MediaQueryListEvent) => void;
export function DarkModeProvider({
children,
storageKey = 'darkMode',
classNameDark = 'dark-mode',
classNameLight = 'light-mode',
}: ProviderProps) {
const [darkMode, setDarkMode] = useState(false);
const listener: Listener = ({matches}) => setMode(matches);
const setMode = (val: boolean) => {
setDarkMode(val);
localStorage.setItem(storageKey, val ? 'true' : 'false');
document.body.classList.add(val ? classNameDark : classNameLight);
document.body.classList.remove(val ? classNameLight : classNameDark);
};
const toggle = useCallback(() => {
setMode(!darkMode);
}, [darkMode]);
useEffect(() => {
const isDarkMode = document.body.classList.contains(classNameDark);
setDarkMode(isDarkMode);
const mql = matchMedia(preferDarkQuery);
if (mql.media === preferDarkQuery) {
mql.addEventListener('change', listener);
return () => mql.removeEventListener('change', listener);
}
}, []);
return (
<DarkModeContext.Provider value={darkMode}>
<DarkModeActionContext.Provider value={{setMode, toggle}}>
{children}
</DarkModeActionContext.Provider>
</DarkModeContext.Provider>
);
}
export const useDarkModeValue = () => {
return useContext(DarkModeContext);
};
export const useDarkModeAction = () => {
return useContext(DarkModeActionContext);
};
export const useDarkMode = () => {
return [
useContext(DarkModeContext),
useContext(DarkModeActionContext),
] as const;
};