/
themeProvider.tsx
77 lines (63 loc) · 2.08 KB
/
themeProvider.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
74
75
76
77
import { createContext, useContext, ReactElement, useState, useEffect } from 'react'
import { DarkMode } from '@appConfig'
export interface ThemeProviderValues {
dark: DarkMode
getDark: () => DarkMode
toggleDark: () => void
}
const defaultValues = {
dark: null,
getDark: () => null,
toggleDark: () => null
}
const ThemeContext = createContext<ThemeProviderValues>(defaultValues)
export const useTheme = (): ThemeProviderValues => useContext(ThemeContext)
// Getting dark mode information from OS!
// You need macOS Mojave + Safari Technology Preview Release 68 to test this currently.
const supportsDarkMode = () => window.matchMedia(`(prefers-color-scheme: dark)`).matches === true
const supportsLightMode = () => window.matchMedia(`(prefers-color-scheme: light)`).matches === true
const getLocalStoragelsDark = () => {
if (typeof localStorage === 'undefined') return null
const dark = localStorage.getItem(`dark`)
if (!dark) return null
return dark === 'dark' ? 'dark' : 'light'
}
export interface DefaultModeProps {
defaultMode: DarkMode
overrideOS: boolean
}
const getDefaultMode = ({ defaultMode, overrideOS }: DefaultModeProps) => {
const lsDark = getLocalStoragelsDark()
if (lsDark !== null) {
return lsDark
} else if (overrideOS) {
return defaultMode
} else if (supportsDarkMode()) {
return 'dark'
} else if (supportsLightMode()) {
return 'light'
} else {
return defaultMode
}
}
interface SitesProviderProps extends DefaultModeProps {
children: React.ReactNode
}
export const ThemeProvider = ({ defaultMode, overrideOS, children }: SitesProviderProps): ReactElement => {
const [dark, setDark] = useState<DarkMode>(null)
useEffect(() => {
setDark(getDark())
}, [])
const getDark = () => getDefaultMode({ defaultMode, overrideOS })
const toggleDark = () => {
if (dark === null) return
const toggle = dark === 'dark' ? 'light' : 'dark'
localStorage.setItem(`dark`, toggle)
setDark(toggle)
}
return (
<ThemeContext.Provider value={{ dark, getDark, toggleDark }}>
{children}
</ThemeContext.Provider>
)
}