From cb54082edab73fd8e7f736e5b883b87e052604a8 Mon Sep 17 00:00:00 2001
From: Eric Bailey <git@esb.lol>
Date: Thu, 7 Aug 2025 11:08:31 -0500
Subject: [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
---
 src/components/Button.tsx | 160 +++++++++++++++++++++++++++++-----------------
 1 file changed, 100 insertions(+), 60 deletions(-)

(limited to 'src/components/Button.tsx')

diff --git a/src/components/Button.tsx b/src/components/Button.tsx
index 57a8530b5..4759b2a88 100644
--- a/src/components/Button.tsx
+++ b/src/components/Button.tsx
@@ -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({
@@ -268,16 +269,37 @@ export const Button = React.forwardRef<View, ButtonProps>(
             hoverStyles.push({
               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.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.negative_700,
-                dim: t.palette.negative_300,
-                dark: t.palette.negative_300,
+                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
-- 
cgit 1.4.1

