about summary refs log tree commit diff
path: root/src/alf/index.tsx
blob: d699de6a5bb222c3b586d683ec88e10d4546caba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import React from 'react'
import {useMediaQuery} from 'react-responsive'

import {createThemes, defaultTheme} from '#/alf/themes'
import {Theme, ThemeName} from '#/alf/types'
import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration'

export {atoms} from '#/alf/atoms'
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<{
  themeName: ThemeName
  theme: Theme
  themes: ReturnType<typeof createThemes>
}>({
  themeName: 'light',
  theme: defaultTheme,
  themes: createThemes({
    hues: {
      primary: BLUE_HUE,
      negative: RED_HUE,
      positive: GREEN_HUE,
    },
  }),
})

export function ThemeProvider({
  children,
  theme: themeName,
}: React.PropsWithChildren<{theme: ThemeName}>) {
  const themes = React.useMemo(() => {
    return createThemes({
      hues: {
        primary: BLUE_HUE,
        negative: RED_HUE,
        positive: GREEN_HUE,
      },
    })
  }, [])
  const theme = themes[themeName]

  return (
    <Context.Provider
      value={React.useMemo(
        () => ({
          themes,
          themeName: themeName,
          theme: theme,
        }),
        [theme, themeName, themes],
      )}>
      {children}
    </Context.Provider>
  )
}

export function useTheme(theme?: ThemeName) {
  const ctx = React.useContext(Context)
  return React.useMemo(() => {
    return theme ? ctx.themes[theme] : ctx.theme
  }, [theme, ctx])
}

export function useBreakpoints() {
  const gtPhone = useMediaQuery({minWidth: 500})
  const gtMobile = useMediaQuery({minWidth: 800})
  const gtTablet = useMediaQuery({minWidth: 1300})
  return {
    gtPhone,
    gtMobile,
    gtTablet,
  }
}