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:
parent
856f80fc6d
commit
ec86282403
15 changed files with 251 additions and 172 deletions
|
@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue