Options for selecting dark theme, fix some white flashes when in dark mode (#2722)

* add dark theme selection to settings/schema

* use `useThemePrefs` where needed

* adjust theme providers to support various themes

* update storybook

* handle web themes

* better themeing for web

* dont show dark theme prefs when color mode is light

* drop the inverted text change on oled theme

* get the color mode inside of `useColorModeTheme`

* use `ThemeName` type everywhere

* typo

* use dim/dark instead of dark/oled

* prevent any fickers on web

* fix styles

* use `dim` for dark default

* more cleanup

* 🤔

* set system background color

* ts
This commit is contained in:
Hailey 2024-02-06 11:43:51 -08:00 committed by GitHub
parent 856f80fc6d
commit ec86282403
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 251 additions and 172 deletions

View file

@ -71,7 +71,7 @@ export const lightPalette = {
export const darkPalette: Palette = {
white: tokens.color.gray_0,
black: tokens.color.gray_1000,
black: tokens.color.trueBlack,
contrast_25: tokens.color.gray_975,
contrast_50: tokens.color.gray_950,
@ -130,6 +130,11 @@ export const darkPalette: Palette = {
negative_975: tokens.color.red_975,
} as const
export const dimPalette: Palette = {
...darkPalette,
black: tokens.color.gray_1000,
} as const
export const light = {
name: 'light',
palette: lightPalette,
@ -191,70 +196,6 @@ export const light = {
},
}
export const dim: Theme = {
name: 'dim',
palette: darkPalette,
atoms: {
text: {
color: darkPalette.white,
},
text_contrast_700: {
color: darkPalette.contrast_800,
},
text_contrast_600: {
color: darkPalette.contrast_700,
},
text_contrast_500: {
color: darkPalette.contrast_600,
},
text_contrast_400: {
color: darkPalette.contrast_500,
},
text_inverted: {
color: darkPalette.black,
},
bg: {
backgroundColor: darkPalette.contrast_50,
},
bg_contrast_25: {
backgroundColor: darkPalette.contrast_100,
},
bg_contrast_50: {
backgroundColor: darkPalette.contrast_200,
},
bg_contrast_100: {
backgroundColor: darkPalette.contrast_300,
},
bg_contrast_200: {
backgroundColor: darkPalette.contrast_400,
},
bg_contrast_300: {
backgroundColor: darkPalette.contrast_500,
},
border: {
borderColor: darkPalette.contrast_200,
},
border_contrast: {
borderColor: darkPalette.contrast_400,
},
shadow_sm: {
...atoms.shadow_sm,
shadowOpacity: 0.7,
shadowColor: tokens.color.trueBlack,
},
shadow_md: {
...atoms.shadow_md,
shadowOpacity: 0.7,
shadowColor: tokens.color.trueBlack,
},
shadow_lg: {
...atoms.shadow_lg,
shadowOpacity: 0.7,
shadowColor: tokens.color.trueBlack,
},
},
}
export const dark: Theme = {
name: 'dark',
palette: darkPalette,
@ -318,3 +259,17 @@ export const dark: Theme = {
},
},
}
export const dim: Theme = {
...dark,
name: 'dim',
atoms: {
...dark.atoms,
text_inverted: {
color: dimPalette.black,
},
bg: {
backgroundColor: dimPalette.black,
},
},
}

View file

@ -1,10 +1,54 @@
import React from 'react'
import {useColorScheme} from 'react-native'
import * as persisted from '#/state/persisted'
import {useThemePrefs} from 'state/shell'
import {isWeb} from 'platform/detection'
import {ThemeName, light, dark, dim} from '#/alf/themes'
import * as SystemUI from 'expo-system-ui'
export function useColorModeTheme(
theme: persisted.Schema['colorMode'],
): 'light' | 'dark' {
export function useColorModeTheme(): ThemeName {
const colorScheme = useColorScheme()
return (theme === 'system' ? colorScheme : theme) || 'light'
const {colorMode, darkTheme} = useThemePrefs()
return React.useMemo(() => {
if (
(colorMode === 'system' && colorScheme === 'light') ||
colorMode === 'light'
) {
updateDocument('light')
updateSystemBackground('light')
return 'light'
} else {
const themeName = darkTheme ?? 'dim'
updateDocument(themeName)
updateSystemBackground(themeName)
return themeName
}
}, [colorMode, darkTheme, colorScheme])
}
function updateDocument(theme: ThemeName) {
// @ts-ignore web only
if (isWeb && typeof window !== 'undefined') {
// @ts-ignore web only
const html = window.document.documentElement
// remove any other color mode classes
html.className = html.className.replace(/(theme)--\w+/g, '')
html.classList.add(`theme--${theme}`)
}
}
function updateSystemBackground(theme: ThemeName) {
switch (theme) {
case 'light':
SystemUI.setBackgroundColorAsync(light.atoms.bg.backgroundColor)
break
case 'dark':
SystemUI.setBackgroundColorAsync(dark.atoms.bg.backgroundColor)
break
case 'dim':
SystemUI.setBackgroundColorAsync(dim.atoms.bg.backgroundColor)
break
}
}