-
-
Notifications
You must be signed in to change notification settings - Fork 420
/
ThemeContext.tsx
73 lines (58 loc) · 1.9 KB
/
ThemeContext.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 type { Dispatch, FC, ReactNode, SetStateAction } from 'react';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { isClient } from '../../helpers/is-client';
import { theme } from '../../theme';
import type { FlowbiteTheme } from './FlowbiteTheme';
export type Mode = 'light' | 'dark';
export interface ThemeContextProps {
mode?: Mode;
theme: FlowbiteTheme;
toggleMode?: () => void | null;
}
export const ThemeContext = createContext<ThemeContextProps>({
theme,
});
interface ThemeProviderProps {
children: ReactNode;
value: ThemeContextProps;
}
export const ThemeProvider: FC<ThemeProviderProps> = ({ children, value }) => {
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
};
export const useTheme: () => ThemeContextProps = () => {
return useContext(ThemeContext);
};
const prefersColorScheme: () => Mode = () => {
if (!isClient()) {
return 'light';
}
return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
export const useThemeMode: () => [Mode, Dispatch<SetStateAction<Mode>>, () => void] = () => {
const onToggleMode = () => {
const newMode = mode === 'dark' ? 'light' : 'dark';
setModeOnBody(newMode);
setMode(newMode);
};
const setModeOnBody = useCallback((mode: Mode) => {
if (!isClient()) {
return;
}
if (mode === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}, []);
const { mode: initialMode, toggleMode = onToggleMode } = useContext(ThemeContext);
const [mode, setMode] = useState<Mode>('light');
useEffect(() => {
if (initialMode) {
setModeOnBody(initialMode);
setMode(initialMode);
} else {
setMode(prefersColorScheme());
}
}, [initialMode, setModeOnBody, setMode]);
return [mode, setMode, toggleMode];
};