From b3e19afd6388c0190f734dbd66497f24fe907a41 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Thu, 21 Dec 2023 15:52:46 -0600 Subject: [PATCH] I think it'll work --- src/alf/styles.ts | 9 ++ src/view/com/Button.tsx | 199 +++++++++++++++++++++++++++++++--- src/view/screens/DebugNew.tsx | 74 ++++++++++++- 3 files changed, 262 insertions(+), 20 deletions(-) diff --git a/src/alf/styles.ts b/src/alf/styles.ts index 7e5b4044ff..abf6123449 100644 --- a/src/alf/styles.ts +++ b/src/alf/styles.ts @@ -260,6 +260,9 @@ export const styles = { ...fontSize, ...fontWeight, ...lineHeight, + center: { + textAlign: 'center', + }, }, flex: { gap, @@ -281,6 +284,12 @@ export const styles = { alignCenter: { alignItems: 'center', }, + alignStart: { + alignItems: 'flex-start', + }, + alignEnd: { + alignItems: 'flex-end', + }, justifyCenter: { justifyContent: 'center', }, diff --git a/src/view/com/Button.tsx b/src/view/com/Button.tsx index fb632d5647..569743943f 100644 --- a/src/view/com/Button.tsx +++ b/src/view/com/Button.tsx @@ -1,32 +1,199 @@ import React from 'react' -import {Pressable, Text} from 'react-native' +import {Pressable, Text, PressableProps, TextProps} from 'react-native' import {useAlf, tokens} from '#/alf' -export function Button({children, ...rest}: React.PropsWithChildren) { +export type ButtonType = + | 'primary' + | 'secondary' + | 'tertiary' + | 'positive' + | 'negative' +export type ButtonSize = 'small' | 'large' + +export type VariantProps = { + type?: ButtonType + size?: ButtonSize +} +type ButtonState = { + pressed: boolean + hovered: boolean + focused: boolean +} +export type ButtonProps = Omit & + VariantProps & { + children: + | ((props: { + state: ButtonState + type?: ButtonType + size?: ButtonSize + }) => React.ReactNode) + | React.ReactNode + | string + } +export type ButtonTextProps = TextProps & VariantProps + +export function Button({children, style, type, size, ...rest}: ButtonProps) { const {styles} = useAlf() + const {baseStyles, hoverStyles} = React.useMemo(() => { + const baseStyles = [] + const hoverStyles = [] + + switch (type) { + case 'primary': + baseStyles.push(styles.backgroundColor.primary) + break + case 'secondary': + baseStyles.push(styles.backgroundColor.l2) + hoverStyles.push(styles.backgroundColor.l1) + break + default: + } + + switch (size) { + case 'large': + baseStyles.push( + styles.padding.py.m, + styles.padding.px.xl, + styles.radius.m, + styles.flex.gap.s, + ) + break + case 'small': + baseStyles.push( + styles.padding.py.s, + styles.padding.px.m, + styles.radius.s, + styles.flex.gap.xs, + ) + break + default: + } + + return { + baseStyles, + hoverStyles, + } + }, [type, size, styles]) + + const [state, setState] = React.useState({ + pressed: false, + hovered: false, + focused: false, + }) + + const onPressIn = React.useCallback(() => { + setState(s => ({ + ...s, + pressed: true, + })) + }, [setState]) + const onPressOut = React.useCallback(() => { + setState(s => ({ + ...s, + pressed: false, + })) + }, [setState]) + const onHoverIn = React.useCallback(() => { + setState(s => ({ + ...s, + hovered: true, + })) + }, [setState]) + const onHoverOut = React.useCallback(() => { + setState(s => ({ + ...s, + hovered: false, + })) + }, [setState]) + const onFocus = React.useCallback(() => { + setState(s => ({ + ...s, + focused: true, + })) + }, [setState]) + const onBlur = React.useCallback(() => { + setState(s => ({ + ...s, + focused: false, + })) + }, [setState]) + return ( [ styles.flex.row, - styles.flex.gap.m, - styles.padding.px.m, - styles.padding.py.s, - styles.radius.m, - styles.backgroundColor.primary, - ]}> + styles.flex.alignCenter, + ...baseStyles, + ...(state.hovered ? hoverStyles : []), + typeof style === 'function' ? style(state) : style, + ]} + onPressIn={onPressIn} + onPressOut={onPressOut} + onHoverIn={onHoverIn} + onHoverOut={onHoverOut} + onFocus={onFocus} + onBlur={onBlur}> {typeof children === 'string' ? ( - + {children} - + + ) : typeof children === 'function' ? ( + children({state, type, size}) ) : ( children )} ) } + +export function ButtonText({ + children, + style, + type, + size, + ...rest +}: ButtonTextProps) { + const {styles} = useAlf() + const textStyles = React.useMemo(() => { + const base = [] + + switch (type) { + case 'primary': + base.push({color: tokens.color.white}) + break + case 'secondary': + base.push(styles.color.l5) + break + default: + } + + switch (size) { + case 'small': + base.push(styles.font.s, {paddingBottom: 1}) + break + case 'large': + base.push(styles.font.m, {paddingBottom: 1}) + break + default: + } + + return base + }, [type, size, styles]) + + console.log(textStyles) + + return ( + + {children} + + ) +} diff --git a/src/view/screens/DebugNew.tsx b/src/view/screens/DebugNew.tsx index c5e50daf3e..e64f5d596e 100644 --- a/src/view/screens/DebugNew.tsx +++ b/src/view/screens/DebugNew.tsx @@ -1,10 +1,11 @@ import React from 'react' import {View} from 'react-native' import {CenteredView, ScrollView} from '#/view/com/util/Views' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {useSetColorMode} from '#/state/shell' import {useAlf, ThemeProvider as Alf} from '#/alf' -import {Button} from '#/view/com/Button' +import {Button, ButtonText} from '#/view/com/Button' import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography' function ThemeSelector() { @@ -13,9 +14,24 @@ function ThemeSelector() { return ( - - - + + + ) } @@ -269,6 +285,56 @@ export function DebugScreen() { + + +

Buttons

+ + + + + + + + + + + +