diff --git a/src/lib/design-system/index.tsx b/src/lib/design-system/index.tsx index dd221d5e29..5eb83f3ec0 100644 --- a/src/lib/design-system/index.tsx +++ b/src/lib/design-system/index.tsx @@ -12,15 +12,19 @@ import merge from 'lodash.merge' import {Theme, light} from './themes' -type ComponentProps = Partial -export type Props = Parameters>[0] & { +type NativeProps = Partial +export type StyleProps = Parameters[0] & + Record +export type ComponentProps = Parameters< + typeof light.pick +>[0] & { /** * Debug mode will log the styles and props to the console */ debug?: boolean } type HeadingElements = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' -type TypeProps = Props & { +type TypeProps = ComponentProps & { as?: HeadingElements } @@ -53,44 +57,35 @@ export function useBreakpoints() { return breakpoints } -export function useStyles(props: Props & T) { +export function usePick(props: ComponentProps) { + const {theme} = React.useContext(Context) + return React.useMemo(() => theme.pick(props), [props, theme]) +} + +export function useStyle(props: StyleProps) { const {theme} = React.useContext(Context) const breakpoints = useBreakpoints() - const { - styles: responsiveStyles, - props: {debug, ...rest}, - } = React.useMemo( - () => theme.pick>(props), - [props, theme], - ) - const styles = React.useMemo(() => { + const {styles: responsiveStyles} = usePick(props) + return React.useMemo(() => { return theme.style( theme.applyBreakpoints(responsiveStyles, breakpoints.active), ) // eslint-disable-next-line react-hooks/exhaustive-deps }, [responsiveStyles, breakpoints.current, theme]) - - if (debug) { - console.debug({styles, props: rest, breakpoints}) - } - - return {styles, props: rest} } -export function useMultiStyle< - O extends Record>[0]>, ->( +export function useStyles>( styles: O, ): { [Name in keyof O]: ReturnType } { const {theme} = React.useContext(Context) const breakpoints = useBreakpoints() - return React.useMemo(() => { return Object.entries(styles).reduce((acc, [key, style]) => { + const responsiveStyles = theme.pick(style).styles acc[key as keyof O] = theme.style( - theme.applyBreakpoints(style, breakpoints.active), + theme.applyBreakpoints(responsiveStyles, breakpoints.active), ) return acc }, {} as {[Name in keyof O]: ReturnType}) @@ -98,24 +93,27 @@ export function useMultiStyle< }, [styles, breakpoints.current, theme]) } -export const Box = React.forwardRef>(function BoxThemed( - {children, style, ...props}, - ref, -) { - const {styles, props: rest} = useStyles(props) - return ( - - {children} - - ) -}) +export const Box = React.forwardRef>( + function BoxThemed({children, style, ...props}, ref) { + const {styles: pickedStyles, props: rest} = usePick(props) + const styles = useStyle(pickedStyles) + if (props.debug) console.log({styles: pickedStyles, props: rest}) + return ( + + {children} + + ) + }, +) -export const Text = React.forwardRef>( +export const Text = React.forwardRef>( function TextThemed({children, style, ...props}, ref) { - const {styles, props: rest} = useStyles({ + const {styles: pickedStyles, props: rest} = usePick(props) + const styles = useStyle({ color: 'text', - ...props, + ...pickedStyles, }) + if (props.debug) console.log({styles, props: rest}) return ( {children} @@ -134,7 +132,7 @@ const asToAriaLevel = { } const asToTypeStyles: { - [key in HeadingElements]: Props + [key in HeadingElements]: ComponentProps } = { h1: { fontSize: 'l', @@ -190,10 +188,12 @@ function createHeadingComponent(element: HeadingElements) { }, default: {}, }) - const {styles, props: rest} = useStyles({ + const {styles: pickedStyles, props: rest} = usePick(props) + const styles = useStyle({ color: 'text', - ...merge(asToTypeStyles[asEl], props), + ...merge(asToTypeStyles[asEl], pickedStyles), }) + if (props.debug) console.debug({styles, props: rest}) return ( > = { type ResponsiveStyles< B extends Breakpoints, S extends Styles, -> = { +> = S & { [Breakpoint in keyof B]?: S } @@ -279,10 +279,10 @@ export const create = < type InnerResponsiveStyles = ResponsiveStyles function pick>( - props: InnerStyles & InnerResponsiveStyles & Props, + props: InnerResponsiveStyles & Props, ) { - const res = {styles: {default: {}}, props: {}} as { - styles: InnerResponsiveStyles & {default: InnerStyles} + const res = {styles: {}, props: {}} as { + styles: InnerResponsiveStyles props: Props } @@ -291,7 +291,7 @@ export const create = < if (value === undefined) continue if (allPropertyKeys.includes(prop)) { // @ts-ignore no index sig, it's fine - res.styles.default[prop] = value + res.styles[prop] = value } else if (keyofBreakpoints.includes(prop)) { // @ts-ignore no index sig, it's fine res.styles[prop] = value @@ -342,19 +342,20 @@ export const create = < function applyBreakpoints( styles: InnerResponsiveStyles, - bp: (keyof typeof breakpoints | 'default')[], + bp: (keyof typeof breakpoints)[], ) { - let s = styles.default as InnerStyles + let s = styles for (const breakpoint of bp) { - s = {...s, ...styles[breakpoint]} + const o = styles[breakpoint] || {} + s = {...s, ...o} } return s } function getActiveBreakpoints({width}: {width: number}) { - const active: (keyof typeof breakpoints | 'default')[] = ['default'] + const active: (keyof typeof breakpoints)[] = [] for (const breakpoint in breakpoints) { if (width >= breakpoints[breakpoint]) { diff --git a/src/view/screens/DesignSystem.tsx b/src/view/screens/DesignSystem.tsx index ab647d2fb6..7034b4785f 100644 --- a/src/view/screens/DesignSystem.tsx +++ b/src/view/screens/DesignSystem.tsx @@ -12,8 +12,8 @@ export const DesignSystemScreen = withAuthRequired( observer(function DesignSystem({}: Props) { return ( - -

+ +

Heading 1