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 6b0e0e5c9d.
* Smooth brain
* Remove outdated docs
* Some docs, fix line-height values, export tokens
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user