Application Layout Framework (#1732)

* Initial library setup

* Add docblocks

* Some cleanup

* New storybook

* Playing around

* Remove silly test, use for...in

* Memo

* Memo

* Add hooks example

* Tweak colors, bit of cleanup

* Improve macro handling

* Add some more examples

* Rename for better diff

* Cleanup

* Add nested context example

* Add todo

* Less break more perf

* Buttons, you get the idea

* Fix test

* Remove temp colors

* Add a few more common macros

* Docs

* Perf improvements

* Alf go brrrr

* Update breakpoint handling

* I think it'll work

* Better naming, better code

* Fix typo

* Some renaming

* More complete pass at Tailwind naming

* Build out storybook

* Playing around with curves

* Revert "Playing around with curves"

This reverts commit 6b0e0e5c9d842a2d9af31b53affe2f6291c3fa0d.

* Smooth brain

* Remove outdated docs

* Some docs, fix line-height values, export tokens
This commit is contained in:
Eric Bailey 2024-01-08 19:43:56 -06:00 committed by GitHub
parent 0ee0554b86
commit a5b474895a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1793 additions and 18 deletions

92
src/alf/index.tsx Normal file
View file

@ -0,0 +1,92 @@
import React from 'react'
import {Dimensions} from 'react-native'
import * as themes from '#/alf/themes'
export * as tokens from '#/alf/tokens'
export {atoms} from '#/alf/atoms'
export * from '#/alf/util/platform'
type BreakpointName = keyof typeof breakpoints
/*
* Breakpoints
*/
const breakpoints: {
[key: string]: number
} = {
gtMobile: 800,
gtTablet: 1200,
}
function getActiveBreakpoints({width}: {width: number}) {
const active: (keyof typeof breakpoints)[] = Object.keys(breakpoints).filter(
breakpoint => width >= breakpoints[breakpoint],
)
return {
active: active[active.length - 1],
gtMobile: active.includes('gtMobile'),
gtTablet: active.includes('gtTablet'),
}
}
/*
* Context
*/
export const Context = React.createContext<{
themeName: themes.ThemeName
theme: themes.Theme
breakpoints: {
active: BreakpointName | undefined
gtMobile: boolean
gtTablet: boolean
}
}>({
themeName: 'light',
theme: themes.light,
breakpoints: {
active: undefined,
gtMobile: false,
gtTablet: false,
},
})
export function ThemeProvider({
children,
theme: themeName,
}: React.PropsWithChildren<{theme: themes.ThemeName}>) {
const theme = themes[themeName]
const [breakpoints, setBreakpoints] = React.useState(() =>
getActiveBreakpoints({width: Dimensions.get('window').width}),
)
React.useEffect(() => {
const listener = Dimensions.addEventListener('change', ({window}) => {
const bp = getActiveBreakpoints({width: window.width})
if (bp.active !== breakpoints.active) setBreakpoints(bp)
})
return listener.remove
}, [breakpoints, setBreakpoints])
return (
<Context.Provider
value={React.useMemo(
() => ({
themeName: themeName,
theme: theme,
breakpoints,
}),
[theme, themeName, breakpoints],
)}>
{children}
</Context.Provider>
)
}
export function useTheme() {
return React.useContext(Context).theme
}
export function useBreakpoints() {
return React.useContext(Context).breakpoints
}