From 6cfafa9e67190f9de3bac340f729b58280299953 Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Sun, 29 May 2022 00:04:24 +0800 Subject: [PATCH] feat: simplify theme --- src/containers/Theme.tsx | 53 +++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/containers/Theme.tsx b/src/containers/Theme.tsx index d6818a5..c6fa123 100644 --- a/src/containers/Theme.tsx +++ b/src/containers/Theme.tsx @@ -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) - ) +// = { + 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 ( - - ) + const themePreference = useThemePreference() + return }