forked from DA0-DA0/dao-dao-ui
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.tsx
105 lines (92 loc) · 2.61 KB
/
index.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {
PropsWithChildren,
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from 'react'
export type UpdateThemeFn = (themeName: Theme) => void
export type SetAccentColorFn = (accentColor: string | undefined) => void
export enum Theme {
Light = 'light',
Dark = 'dark',
}
export interface IThemeContext {
theme: Theme
themeChangeCount: number
updateTheme: UpdateThemeFn
// Automatically falls back to brand color.
accentColor: string
setAccentColor: SetAccentColorFn
}
export const DEFAULT_THEME_NAME = Theme.Dark
export const DEFAULT_THEME: IThemeContext = {
theme: DEFAULT_THEME_NAME,
themeChangeCount: 0,
updateTheme: (themeName: string) => {
console.error(`do-nothing update for ${themeName}`)
},
accentColor: '',
setAccentColor: (accentColor: string | undefined) => {
console.error(`do-nothing update for ${accentColor}`)
},
}
export const ThemeContext = createContext<IThemeContext>(DEFAULT_THEME)
export const ThemeProvider = ({
children,
theme,
themeChangeCount,
updateTheme,
}: PropsWithChildren<
Omit<IThemeContext, 'accentColor' | 'setAccentColor'>
>) => {
// This is the same as the `useNamedThemeColor` hook, but that hook assumes it
// is wrapped in this ThemeProvider, so let's just get the brand manually.
const [accentColor, _setAccentColor] = useState(
`rgb(${getNamedColorFromDOM('brand') || '123, 97, 255'})`
)
const setAccentColor = useCallback(
(accentColor: string | undefined) =>
_setAccentColor(accentColor || `rgb(${getNamedColorFromDOM('brand')})`),
[]
)
return (
<ThemeContext.Provider
value={useMemo(
() => ({
...DEFAULT_THEME,
theme,
themeChangeCount,
updateTheme,
accentColor,
setAccentColor,
}),
[accentColor, setAccentColor, theme, themeChangeCount, updateTheme]
)}
>
{children}
</ThemeContext.Provider>
)
}
export const useThemeContext = () => useContext(ThemeContext)
export const useNamedThemeColor = (colorName: string) => {
const { themeChangeCount } = useThemeContext()
const [color, setColor] = useState<string | undefined>(
getNamedColorFromDOM(colorName)
)
useEffect(
() => {
setColor(getNamedColorFromDOM(colorName))
},
// Re-fetch color when theme changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
[themeChangeCount]
)
return color
}
const getNamedColorFromDOM = (colorName: string) =>
typeof getComputedStyle !== 'undefined'
? getComputedStyle(document.body).getPropertyValue(`--${colorName}`).trim()
: undefined