parent
1b992d5d6b
commit
ae9f893723
|
@ -27,7 +27,7 @@ export type ButtonColor =
|
||||||
| 'gradient_sunset'
|
| 'gradient_sunset'
|
||||||
| 'gradient_nordic'
|
| 'gradient_nordic'
|
||||||
| 'gradient_bonfire'
|
| 'gradient_bonfire'
|
||||||
export type ButtonSize = 'small' | 'large'
|
export type ButtonSize = 'tiny' | 'small' | 'large'
|
||||||
export type ButtonShape = 'round' | 'square' | 'default'
|
export type ButtonShape = 'round' | 'square' | 'default'
|
||||||
export type VariantProps = {
|
export type VariantProps = {
|
||||||
/**
|
/**
|
||||||
|
@ -48,25 +48,32 @@ export type VariantProps = {
|
||||||
shape?: ButtonShape
|
shape?: ButtonShape
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ButtonProps = React.PropsWithChildren<
|
export type ButtonState = {
|
||||||
Pick<PressableProps, 'disabled' | 'onPress'> &
|
hovered: boolean
|
||||||
|
focused: boolean
|
||||||
|
pressed: boolean
|
||||||
|
disabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ButtonContext = VariantProps & ButtonState
|
||||||
|
|
||||||
|
export type ButtonProps = Pick<
|
||||||
|
PressableProps,
|
||||||
|
'disabled' | 'onPress' | 'testID'
|
||||||
|
> &
|
||||||
AccessibilityProps &
|
AccessibilityProps &
|
||||||
VariantProps & {
|
VariantProps & {
|
||||||
testID?: string
|
testID?: string
|
||||||
label: string
|
label: string
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
|
children:
|
||||||
|
| React.ReactNode
|
||||||
|
| string
|
||||||
|
| ((context: ButtonContext) => React.ReactNode | string)
|
||||||
}
|
}
|
||||||
>
|
|
||||||
export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean}
|
export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean}
|
||||||
|
|
||||||
const Context = React.createContext<
|
const Context = React.createContext<VariantProps & ButtonState>({
|
||||||
VariantProps & {
|
|
||||||
hovered: boolean
|
|
||||||
focused: boolean
|
|
||||||
pressed: boolean
|
|
||||||
disabled: boolean
|
|
||||||
}
|
|
||||||
>({
|
|
||||||
hovered: false,
|
hovered: false,
|
||||||
focused: false,
|
focused: false,
|
||||||
pressed: false,
|
pressed: false,
|
||||||
|
@ -277,6 +284,8 @@ export function Button({
|
||||||
baseStyles.push({paddingVertical: 15}, a.px_2xl, a.rounded_sm, a.gap_md)
|
baseStyles.push({paddingVertical: 15}, a.px_2xl, a.rounded_sm, a.gap_md)
|
||||||
} else if (size === 'small') {
|
} else if (size === 'small') {
|
||||||
baseStyles.push({paddingVertical: 9}, a.px_lg, a.rounded_sm, a.gap_sm)
|
baseStyles.push({paddingVertical: 9}, a.px_lg, a.rounded_sm, a.gap_sm)
|
||||||
|
} else if (size === 'tiny') {
|
||||||
|
baseStyles.push({paddingVertical: 4}, a.px_sm, a.rounded_xs, a.gap_xs)
|
||||||
}
|
}
|
||||||
} else if (shape === 'round' || shape === 'square') {
|
} else if (shape === 'round' || shape === 'square') {
|
||||||
if (size === 'large') {
|
if (size === 'large') {
|
||||||
|
@ -287,14 +296,20 @@ export function Button({
|
||||||
}
|
}
|
||||||
} else if (size === 'small') {
|
} else if (size === 'small') {
|
||||||
baseStyles.push({height: 40, width: 40})
|
baseStyles.push({height: 40, width: 40})
|
||||||
|
} else if (size === 'tiny') {
|
||||||
|
baseStyles.push({height: 20, width: 20})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shape === 'round') {
|
if (shape === 'round') {
|
||||||
baseStyles.push(a.rounded_full)
|
baseStyles.push(a.rounded_full)
|
||||||
} else if (shape === 'square') {
|
} else if (shape === 'square') {
|
||||||
|
if (size === 'tiny') {
|
||||||
|
baseStyles.push(a.rounded_xs)
|
||||||
|
} else {
|
||||||
baseStyles.push(a.rounded_sm)
|
baseStyles.push(a.rounded_sm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
baseStyles,
|
baseStyles,
|
||||||
|
@ -338,7 +353,7 @@ export function Button({
|
||||||
}
|
}
|
||||||
}, [variant, color])
|
}, [variant, color])
|
||||||
|
|
||||||
const context = React.useMemo(
|
const context = React.useMemo<ButtonContext>(
|
||||||
() => ({
|
() => ({
|
||||||
...state,
|
...state,
|
||||||
variant,
|
variant,
|
||||||
|
@ -349,6 +364,8 @@ export function Button({
|
||||||
[state, variant, color, size, disabled],
|
[state, variant, color, size, disabled],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const flattenedBaseStyles = flatten(baseStyles)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
role="button"
|
role="button"
|
||||||
|
@ -362,15 +379,14 @@ export function Button({
|
||||||
disabled: disabled || false,
|
disabled: disabled || false,
|
||||||
}}
|
}}
|
||||||
style={[
|
style={[
|
||||||
flatten(style),
|
|
||||||
a.flex_row,
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
a.overflow_hidden,
|
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
...baseStyles,
|
flattenedBaseStyles,
|
||||||
...(state.hovered || state.pressed ? hoverStyles : []),
|
...(state.hovered || state.pressed ? hoverStyles : []),
|
||||||
...(state.focused ? focusStyles : []),
|
...(state.focused ? focusStyles : []),
|
||||||
|
flatten(style),
|
||||||
]}
|
]}
|
||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
onPressOut={onPressOut}
|
onPressOut={onPressOut}
|
||||||
|
@ -379,6 +395,13 @@ export function Button({
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
onBlur={onBlur}>
|
onBlur={onBlur}>
|
||||||
{variant === 'gradient' && (
|
{variant === 'gradient' && (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.absolute,
|
||||||
|
a.inset_0,
|
||||||
|
a.overflow_hidden,
|
||||||
|
{borderRadius: flattenedBaseStyles.borderRadius},
|
||||||
|
]}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={
|
colors={
|
||||||
state.hovered || state.pressed || state.focused
|
state.hovered || state.pressed || state.focused
|
||||||
|
@ -390,10 +413,13 @@ export function Button({
|
||||||
end={{x: 1, y: 1}}
|
end={{x: 1, y: 1}}
|
||||||
style={[a.absolute, a.inset_0]}
|
style={[a.absolute, a.inset_0]}
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
<Context.Provider value={context}>
|
<Context.Provider value={context}>
|
||||||
{typeof children === 'string' ? (
|
{typeof children === 'string' ? (
|
||||||
<ButtonText>{children}</ButtonText>
|
<ButtonText>{children}</ButtonText>
|
||||||
|
) : typeof children === 'function' ? (
|
||||||
|
children(context)
|
||||||
) : (
|
) : (
|
||||||
children
|
children
|
||||||
)}
|
)}
|
||||||
|
@ -493,6 +519,8 @@ export function useSharedButtonTextStyles() {
|
||||||
|
|
||||||
if (size === 'large') {
|
if (size === 'large') {
|
||||||
baseStyles.push(a.text_md, android({paddingBottom: 1}))
|
baseStyles.push(a.text_md, android({paddingBottom: 1}))
|
||||||
|
} else if (size === 'tiny') {
|
||||||
|
baseStyles.push(a.text_xs, android({paddingBottom: 1}))
|
||||||
} else {
|
} else {
|
||||||
baseStyles.push(a.text_sm, android({paddingBottom: 1}))
|
baseStyles.push(a.text_sm, android({paddingBottom: 1}))
|
||||||
}
|
}
|
||||||
|
@ -514,9 +542,11 @@ export function ButtonText({children, style, ...rest}: ButtonTextProps) {
|
||||||
export function ButtonIcon({
|
export function ButtonIcon({
|
||||||
icon: Comp,
|
icon: Comp,
|
||||||
position,
|
position,
|
||||||
|
size: iconSize,
|
||||||
}: {
|
}: {
|
||||||
icon: React.ComponentType<SVGIconProps>
|
icon: React.ComponentType<SVGIconProps>
|
||||||
position?: 'left' | 'right'
|
position?: 'left' | 'right'
|
||||||
|
size?: SVGIconProps['size']
|
||||||
}) {
|
}) {
|
||||||
const {size, disabled} = useButtonContext()
|
const {size, disabled} = useButtonContext()
|
||||||
const textStyles = useSharedButtonTextStyles()
|
const textStyles = useSharedButtonTextStyles()
|
||||||
|
@ -532,7 +562,9 @@ export function ButtonIcon({
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
<Comp
|
<Comp
|
||||||
size={size === 'large' ? 'md' : 'sm'}
|
size={
|
||||||
|
iconSize ?? (size === 'large' ? 'md' : size === 'tiny' ? 'xs' : 'sm')
|
||||||
|
}
|
||||||
style={[{color: textStyles.color, pointerEvents: 'none'}]}
|
style={[{color: textStyles.color, pointerEvents: 'none'}]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
Loading…
Reference in New Issue