From 0eed1cfec1b0caac35930529dfd9ac92bf38606f Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 20 Sep 2024 11:38:51 -0500 Subject: [Neue] Buttons (#5406) * Re-align button sizing (cherry picked from commit bcec243bb59dfe468313d98ba61f464d9750feec) * Use large, small, tiny (cherry picked from commit 1dc333c2993ab7f2e0ac750c0670dcec9a7069d0) * Tweaks --- src/components/Button.tsx | 148 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 37 deletions(-) (limited to 'src/components/Button.tsx') diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 704aa9d98..8728b88c2 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -14,7 +14,7 @@ import { } from 'react-native' import {LinearGradient} from 'expo-linear-gradient' -import {android, atoms as a, flatten, select, tokens, useTheme} from '#/alf' +import {atoms as a, flatten, select, tokens, useTheme, web} from '#/alf' import {Props as SVGIconProps} from '#/components/icons/common' import {Text} from '#/components/Typography' @@ -30,7 +30,7 @@ export type ButtonColor = | 'gradient_sunset' | 'gradient_nordic' | 'gradient_bonfire' -export type ButtonSize = 'tiny' | 'xsmall' | 'small' | 'medium' | 'large' +export type ButtonSize = 'tiny' | 'small' | 'large' export type ButtonShape = 'round' | 'square' | 'default' export type VariantProps = { /** @@ -343,39 +343,46 @@ export const Button = React.forwardRef( if (shape === 'default') { if (size === 'large') { - baseStyles.push( - {paddingVertical: 15}, - a.px_2xl, - a.rounded_sm, - a.gap_md, - ) - } else if (size === 'medium') { - baseStyles.push( - {paddingVertical: 12}, - a.px_2xl, - a.rounded_sm, - a.gap_md, - ) + baseStyles.push({ + paddingVertical: 13, + paddingHorizontal: 20, + borderRadius: 8, + gap: 8, + }) } else if (size === 'small') { - baseStyles.push({paddingVertical: 9}, a.px_lg, a.rounded_sm, a.gap_sm) - } else if (size === 'xsmall') { - baseStyles.push({paddingVertical: 6}, a.px_sm, a.rounded_sm, a.gap_sm) + baseStyles.push({ + paddingVertical: 8, + paddingHorizontal: 12, + borderRadius: 6, + gap: 6, + }) } else if (size === 'tiny') { - baseStyles.push({paddingVertical: 4}, a.px_sm, a.rounded_xs, a.gap_xs) + baseStyles.push({ + paddingVertical: 4, + paddingHorizontal: 8, + borderRadius: 4, + gap: 4, + }) } } else if (shape === 'round' || shape === 'square') { if (size === 'large') { if (shape === 'round') { - baseStyles.push({height: 54, width: 54}) + baseStyles.push({height: 46, width: 46}) } else { - baseStyles.push({height: 50, width: 50}) + baseStyles.push({height: 44, width: 44}) } } else if (size === 'small') { - baseStyles.push({height: 34, width: 34}) - } else if (size === 'xsmall') { - baseStyles.push({height: 28, width: 28}) + if (shape === 'round') { + baseStyles.push({height: 36, width: 36}) + } else { + baseStyles.push({height: 34, width: 34}) + } } else if (size === 'tiny') { - baseStyles.push({height: 20, width: 20}) + if (shape === 'round') { + baseStyles.push({height: 22, width: 22}) + } else { + baseStyles.push({height: 21, width: 21}) + } } if (shape === 'round') { @@ -619,11 +626,11 @@ export function useSharedButtonTextStyles() { } if (size === 'large') { - baseStyles.push(a.text_md, android({paddingBottom: 1})) + baseStyles.push(a.text_md, a.leading_tight, web({paddingTop: 1})) + } else if (size === 'small') { + baseStyles.push(a.text_sm, a.leading_tight, web({paddingTop: 1})) } else if (size === 'tiny') { - baseStyles.push(a.text_xs, android({paddingBottom: 1})) - } else { - baseStyles.push(a.text_sm, android({paddingBottom: 1})) + baseStyles.push(a.text_xs, a.leading_tight) } return StyleSheet.flatten(baseStyles) @@ -643,31 +650,98 @@ export function ButtonText({children, style, ...rest}: ButtonTextProps) { export function ButtonIcon({ icon: Comp, position, - size: iconSize, + size, }: { icon: React.ComponentType position?: 'left' | 'right' size?: SVGIconProps['size'] }) { - const {size, disabled} = useButtonContext() + const {size: buttonSize, disabled} = useButtonContext() const textStyles = useSharedButtonTextStyles() + const {iconSize, iconContainerSize} = React.useMemo(() => { + /** + * Pre-set icon sizes for different button sizes + */ + const iconSizeShorthand = + size ?? + (({ + large: 'sm', + small: 'xs', + tiny: 'xs', + }[buttonSize || 'small'] || 'sm') as Exclude< + SVGIconProps['size'], + undefined + >) + + /* + * Copied here from icons/common.tsx so we can tweak if we need to, but + * also so that we can calculate transforms. + */ + const iconSize = { + xs: 12, + sm: 16, + md: 20, + lg: 24, + xl: 28, + '2xl': 32, + }[iconSizeShorthand] + + /* + * Goal here is to match rendered text size so that different size icons + * don't increase button size + */ + const iconContainerSize = { + large: 18, + small: 16, + tiny: 13, + }[buttonSize || 'small'] + + return { + iconSize, + iconContainerSize, + } + }, [buttonSize, size]) return ( - + + + ) } -- cgit 1.4.1