feat: simplify theme

This commit is contained in:
EnixCoda 2022-05-29 00:04:24 +08:00
parent 3cdd3fa600
commit 6cfafa9e67

View file

@ -1,19 +1,46 @@
import { ThemeProvider } from '@primer/react'
import theme from '@primer/react/lib-esm/theme'
import * as React from 'react'
const getIsPreferDarkTheme = () => {
const colorMode = document.documentElement.dataset.colorMode
return (
colorMode === 'dark' ||
(colorMode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)
)
// <html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" ...
// <html lang="en" data-color-mode="light" data-light-theme="light" data-dark-theme="dark" ...
// <html lang="en" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" ...
const colorModeMap: Record<string, 'night' | 'day'> = {
dark: 'night',
light: 'day',
}
// No need to watch the property as it does not change in repo pages
function usePreferDarkTheme() {
const [prefer, setPrefer] = React.useState(getIsPreferDarkTheme)
const validColorSchemes = Object.keys(theme.colorSchemes) as EnumString<
| 'light'
| 'light_high_contrast'
| 'light_colorblind'
| 'light_tritanopia'
| 'dark'
| 'dark_dimmed'
| 'dark_high_contrast'
| 'dark_colorblind'
| 'dark_tritanopia'
>[]
// The `*_tritanopia` themes are actually not bundled within @primer/react@35.2.2
// TODO: Upgrade @primer/react to support these themes
// BUT: Do not remove the validation, there might be other themes in future
const getPreferenceFromDOM = () => {
const { colorMode, lightTheme, darkTheme } = document.documentElement.dataset
return {
colorMode: (colorMode && colorModeMap[colorMode]) || 'auto',
dayScheme: lightTheme && validColorSchemes.includes(lightTheme) ? lightTheme : undefined,
nightScheme: darkTheme && validColorSchemes.includes(darkTheme) ? darkTheme : undefined,
} as const
}
function useThemePreference() {
const [prefer, setPrefer] = React.useState(getPreferenceFromDOM)
React.useEffect(() => {
const match = window.matchMedia('(prefers-color-scheme: dark)')
const update = () => setPrefer(match.matches) // `.matches` will update on media change
const update = () => setPrefer(getPreferenceFromDOM)
match.addEventListener('change', update)
return () => match.removeEventListener('change', update)
}, [])
@ -21,8 +48,6 @@ function usePreferDarkTheme() {
}
export function Theme({ children }: React.PropsWithChildren<{}>) {
const preferDarkTheme = usePreferDarkTheme()
return (
<ThemeProvider colorMode={preferDarkTheme ? 'night' : 'day'} dayScheme="" {...{ children }} />
)
const themePreference = useThemePreference()
return <ThemeProvider {...themePreference} {...{ children }} />
}