diff options
Diffstat (limited to 'src/alf/index.tsx')
-rw-r--r-- | src/alf/index.tsx | 101 |
1 files changed, 89 insertions, 12 deletions
diff --git a/src/alf/index.tsx b/src/alf/index.tsx index d699de6a5..f9d93d4ca 100644 --- a/src/alf/index.tsx +++ b/src/alf/index.tsx @@ -1,25 +1,47 @@ import React from 'react' import {useMediaQuery} from 'react-responsive' +import { + computeFontScaleMultiplier, + getFontFamily, + getFontScale, + setFontFamily as persistFontFamily, + setFontScale as persistFontScale, +} from '#/alf/fonts' import {createThemes, defaultTheme} from '#/alf/themes' import {Theme, ThemeName} from '#/alf/types' import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration' +import {Device} from '#/storage' export {atoms} from '#/alf/atoms' +export * from '#/alf/fonts' export * as tokens from '#/alf/tokens' export * from '#/alf/types' export * from '#/alf/util/flatten' export * from '#/alf/util/platform' export * from '#/alf/util/themeSelector' -/* - * Context - */ -export const Context = React.createContext<{ +export type Alf = { themeName: ThemeName theme: Theme themes: ReturnType<typeof createThemes> -}>({ + fonts: { + scale: Exclude<Device['fontScale'], undefined> + scaleMultiplier: number + family: Device['fontFamily'] + setFontScale: (fontScale: Exclude<Device['fontScale'], undefined>) => void + setFontFamily: (fontFamily: Device['fontFamily']) => void + } + /** + * Feature flags or other gated options + */ + flags: {} +} + +/* + * Context + */ +export const Context = React.createContext<Alf>({ themeName: 'light', theme: defaultTheme, themes: createThemes({ @@ -29,12 +51,48 @@ export const Context = React.createContext<{ positive: GREEN_HUE, }, }), + fonts: { + scale: getFontScale(), + scaleMultiplier: computeFontScaleMultiplier(getFontScale()), + family: getFontFamily(), + setFontScale: () => {}, + setFontFamily: () => {}, + }, + flags: {}, }) export function ThemeProvider({ children, theme: themeName, }: React.PropsWithChildren<{theme: ThemeName}>) { + const [fontScale, setFontScale] = React.useState<Alf['fonts']['scale']>(() => + getFontScale(), + ) + const [fontScaleMultiplier, setFontScaleMultiplier] = React.useState(() => + computeFontScaleMultiplier(fontScale), + ) + const setFontScaleAndPersist = React.useCallback< + Alf['fonts']['setFontScale'] + >( + fontScale => { + setFontScale(fontScale) + persistFontScale(fontScale) + setFontScaleMultiplier(computeFontScaleMultiplier(fontScale)) + }, + [setFontScale], + ) + const [fontFamily, setFontFamily] = React.useState<Alf['fonts']['family']>( + () => getFontFamily(), + ) + const setFontFamilyAndPersist = React.useCallback< + Alf['fonts']['setFontFamily'] + >( + fontFamily => { + setFontFamily(fontFamily) + persistFontFamily(fontFamily) + }, + [setFontFamily], + ) const themes = React.useMemo(() => { return createThemes({ hues: { @@ -44,28 +102,47 @@ export function ThemeProvider({ }, }) }, []) - const theme = themes[themeName] return ( <Context.Provider - value={React.useMemo( + value={React.useMemo<Alf>( () => ({ themes, themeName: themeName, - theme: theme, + theme: themes[themeName], + fonts: { + scale: fontScale, + scaleMultiplier: fontScaleMultiplier, + family: fontFamily, + setFontScale: setFontScaleAndPersist, + setFontFamily: setFontFamilyAndPersist, + }, + flags: {}, }), - [theme, themeName, themes], + [ + themeName, + themes, + fontScale, + setFontScaleAndPersist, + fontFamily, + setFontFamilyAndPersist, + fontScaleMultiplier, + ], )}> {children} </Context.Provider> ) } +export function useAlf() { + return React.useContext(Context) +} + export function useTheme(theme?: ThemeName) { - const ctx = React.useContext(Context) + const alf = useAlf() return React.useMemo(() => { - return theme ? ctx.themes[theme] : ctx.theme - }, [theme, ctx]) + return theme ? alf.themes[theme] : alf.theme + }, [theme, alf]) } export function useBreakpoints() { |