[APP-1310] Button refresh (#8758)

* Rm gradient buttons from Storybook

* TEMP move storybook button section

* Remove gradient_sky

* Remove actual defs for gradient_sky and gradient_primary

* Remove other gradient defs

* Remove gradient support entirely

* Deprecate 'variant' in favor of 'color'

* Fork base styles codepath to make variant deprecation more obvious

* Remove text styles for when no color is set, never been used

* Fork text styles codepath to make variant deprecation more obvious

* Revert temp storybook commit, remove deprecated values

* Replace remaining gradient button usage

* Update Buttons storybook section

* Update tiny styles

* Update small styles

* Update large sizes

* Ensure proper alignment of buttons in storybook

* Update button colors

* Rename negative_secondary to negative_subtle

* Remove unnecessary select()

* Update icon size and gap

* Update negative_subtle styles

* Custom button colors

* Add borderCurve
This commit is contained in:
Eric Bailey
2025-08-07 11:08:31 -05:00
committed by GitHub
parent 20ac2e2733
commit cb54082eda
4 changed files with 170 additions and 206 deletions
+100 -60
View File
@@ -37,7 +37,8 @@ export type ButtonColor =
| 'secondary'
| 'secondary_inverted'
| 'negative'
| 'negative_secondary'
| 'primary_subtle'
| 'negative_subtle'
export type ButtonSize = 'tiny' | 'small' | 'large'
export type ButtonShape = 'round' | 'square' | 'default'
export type VariantProps = {
@@ -214,7 +215,11 @@ export const Button = React.forwardRef<View, ButtonProps>(
)
const {baseStyles, hoverStyles} = React.useMemo(() => {
const baseStyles: ViewStyle[] = []
const baseStyles: ViewStyle[] = [
{
borderCurve: 'continuous',
},
]
const hoverStyles: ViewStyle[] = []
/*
@@ -233,19 +238,15 @@ export const Button = React.forwardRef<View, ButtonProps>(
})
} else {
baseStyles.push({
backgroundColor: select(t.name, {
light: t.palette.primary_700,
dim: t.palette.primary_300,
dark: t.palette.primary_300,
}),
backgroundColor: t.palette.primary_200,
})
}
} else if (color === 'secondary') {
if (!disabled) {
baseStyles.push(t.atoms.bg_contrast_25)
hoverStyles.push(t.atoms.bg_contrast_50)
hoverStyles.push(t.atoms.bg_contrast_100)
} else {
baseStyles.push(t.atoms.bg_contrast_100)
baseStyles.push(t.atoms.bg_contrast_50)
}
} else if (color === 'secondary_inverted') {
if (!disabled) {
@@ -253,7 +254,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
backgroundColor: t.palette.contrast_900,
})
hoverStyles.push({
backgroundColor: t.palette.contrast_950,
backgroundColor: t.palette.contrast_975,
})
} else {
baseStyles.push({
@@ -269,15 +270,36 @@ export const Button = React.forwardRef<View, ButtonProps>(
backgroundColor: t.palette.negative_600,
})
} else {
baseStyles.push({
backgroundColor: t.palette.negative_700,
})
}
} else if (color === 'primary_subtle') {
if (!disabled) {
baseStyles.push({
backgroundColor: select(t.name, {
light: t.palette.negative_700,
dim: t.palette.negative_300,
dark: t.palette.negative_300,
light: t.palette.primary_50,
dim: t.palette.primary_100,
dark: t.palette.primary_100,
}),
})
hoverStyles.push({
backgroundColor: select(t.name, {
light: t.palette.primary_100,
dim: t.palette.primary_200,
dark: t.palette.primary_200,
}),
})
} else {
baseStyles.push({
backgroundColor: select(t.name, {
light: t.palette.primary_25,
dim: t.palette.primary_50,
dark: t.palette.primary_50,
}),
})
}
} else if (color === 'negative_secondary') {
} else if (color === 'negative_subtle') {
if (!disabled) {
baseStyles.push({
backgroundColor: select(t.name, {
@@ -296,7 +318,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
} else {
baseStyles.push({
backgroundColor: select(t.name, {
light: t.palette.negative_100,
light: t.palette.negative_25,
dim: t.palette.negative_50,
dark: t.palette.negative_50,
}),
@@ -407,7 +429,7 @@ export const Button = React.forwardRef<View, ButtonProps>(
})
}
}
} else if (color === 'negative_secondary') {
} else if (color === 'negative_subtle') {
if (variant === 'outline') {
baseStyles.push(a.border, t.atoms.bg, {
borderWidth: 1,
@@ -442,44 +464,48 @@ export const Button = React.forwardRef<View, ButtonProps>(
if (shape === 'default') {
if (size === 'large') {
baseStyles.push({
paddingVertical: 13,
paddingHorizontal: 20,
borderRadius: 8,
gap: 8,
paddingVertical: 14,
paddingHorizontal: 24,
borderRadius: 10,
gap: 4,
})
} else if (size === 'small') {
baseStyles.push({
paddingVertical: 9,
paddingVertical: 8,
paddingHorizontal: 12,
borderRadius: 6,
gap: 6,
borderRadius: 8,
gap: 3,
})
} else if (size === 'tiny') {
baseStyles.push({
paddingVertical: 4,
paddingVertical: 6,
paddingHorizontal: 8,
borderRadius: 4,
gap: 4,
borderRadius: 6,
gap: 2,
})
}
} else if (shape === 'round' || shape === 'square') {
/*
* These sizes match the actual rendered size on screen, based on
* Chrome's web inspector
*/
if (size === 'large') {
if (shape === 'round') {
baseStyles.push({height: 46, width: 46})
baseStyles.push({height: 45, width: 45})
} else {
baseStyles.push({height: 44, width: 44})
baseStyles.push({height: 45, width: 45})
}
} else if (size === 'small') {
if (shape === 'round') {
baseStyles.push({height: 34, width: 34})
baseStyles.push({height: 33, width: 33})
} else {
baseStyles.push({height: 34, width: 34})
baseStyles.push({height: 33, width: 33})
}
} else if (size === 'tiny') {
if (shape === 'round') {
baseStyles.push({height: 22, width: 22})
baseStyles.push({height: 25, width: 25})
} else {
baseStyles.push({height: 21, width: 21})
baseStyles.push({height: 25, width: 25})
}
}
@@ -487,7 +513,9 @@ export const Button = React.forwardRef<View, ButtonProps>(
baseStyles.push(a.rounded_full)
} else if (shape === 'square') {
if (size === 'tiny') {
baseStyles.push(a.rounded_xs)
baseStyles.push({
borderRadius: 6,
})
} else {
baseStyles.push(a.rounded_sm)
}
@@ -567,51 +595,64 @@ export function useSharedButtonTextStyles() {
if (!disabled) {
baseStyles.push({color: t.palette.white})
} else {
baseStyles.push({color: t.palette.white, opacity: 0.5})
baseStyles.push({color: t.palette.white})
}
} else if (color === 'secondary') {
if (!disabled) {
baseStyles.push({
color: t.palette.contrast_700,
})
baseStyles.push(t.atoms.text_contrast_medium)
} else {
baseStyles.push({
color: t.palette.contrast_400,
color: t.palette.contrast_300,
})
}
} else if (color === 'secondary_inverted') {
if (!disabled) {
baseStyles.push({
color: t.palette.contrast_50,
})
baseStyles.push(t.atoms.text_inverted)
} else {
baseStyles.push({
color: t.palette.contrast_400,
color: t.palette.contrast_300,
})
}
} else if (color === 'negative') {
if (!disabled) {
baseStyles.push({color: t.palette.white})
} else {
baseStyles.push({color: t.palette.white, opacity: 0.5})
baseStyles.push({color: t.palette.negative_300})
}
} else if (color === 'negative_secondary') {
} else if (color === 'primary_subtle') {
if (!disabled) {
baseStyles.push({
color: select(t.name, {
light: t.palette.negative_500,
dim: t.palette.negative_950,
dark: t.palette.negative_900,
light: t.palette.primary_600,
dim: t.palette.primary_800,
dark: t.palette.primary_800,
}),
})
} else {
baseStyles.push({
color: select(t.name, {
light: t.palette.negative_500,
dim: t.palette.negative_700,
dark: t.palette.negative_700,
light: t.palette.primary_200,
dim: t.palette.primary_200,
dark: t.palette.primary_200,
}),
})
}
} else if (color === 'negative_subtle') {
if (!disabled) {
baseStyles.push({
color: select(t.name, {
light: t.palette.negative_600,
dim: t.palette.negative_800,
dark: t.palette.negative_800,
}),
})
} else {
baseStyles.push({
color: select(t.name, {
light: t.palette.negative_200,
dim: t.palette.negative_200,
dark: t.palette.negative_200,
}),
opacity: 0.5,
})
}
}
@@ -693,7 +734,7 @@ export function useSharedButtonTextStyles() {
baseStyles.push({color: t.palette.negative_400, opacity: 0.5})
}
}
} else if (color === 'negative_secondary') {
} else if (color === 'negative_subtle') {
if (variant === 'outline') {
if (!disabled) {
baseStyles.push({color: t.palette.negative_400})
@@ -716,7 +757,7 @@ export function useSharedButtonTextStyles() {
if (size === 'large') {
baseStyles.push(a.text_md, a.leading_tight)
} else if (size === 'small') {
baseStyles.push(a.text_sm, a.leading_tight)
baseStyles.push(a.text_md, a.leading_tight)
} else if (size === 'tiny') {
baseStyles.push(a.text_xs, a.leading_tight)
}
@@ -737,14 +778,16 @@ export function ButtonText({children, style, ...rest}: ButtonTextProps) {
export function ButtonIcon({
icon: Comp,
position,
size,
}: {
icon: React.ComponentType<SVGIconProps>
/**
* @deprecated no longer needed
*/
position?: 'left' | 'right'
size?: SVGIconProps['size']
}) {
const {size: buttonSize, disabled} = useButtonContext()
const {size: buttonSize} = useButtonContext()
const textStyles = useSharedButtonTextStyles()
const {iconSize, iconContainerSize} = React.useMemo(() => {
/**
@@ -779,8 +822,8 @@ export function ButtonIcon({
* don't increase button size
*/
const iconContainerSize = {
large: 18,
small: 16,
large: 17,
small: 17,
tiny: 13,
}[buttonSize || 'small']
@@ -797,9 +840,6 @@ export function ButtonIcon({
{
width: iconContainerSize,
height: iconContainerSize,
opacity: disabled ? 0.7 : 1,
marginLeft: position === 'left' ? -2 : 0,
marginRight: position === 'right' ? -2 : 0,
},
]}>
<View
+1 -1
View File
@@ -240,7 +240,7 @@ function DialogInner({
label={_(msg`Remove live status`)}
onPress={() => removeLiveStatus()}
size={platform({native: 'large', web: 'small'})}
color="negative_secondary"
color="negative_subtle"
variant="solid"
disabled={isRemovingLiveStatus || isGoingLive}>
<ButtonText>