Skip to content

Commit

Permalink
feat: add gradient variants to Button (#7514)
Browse files Browse the repository at this point in the history
* add gradient variants to Button

* fix for gradient isPending, outline, hover

* revert line

* fix fillStyle/backgroundColor, add background for other states

* more styling fixes

* Fix disabled and HCM styles

---------

Co-authored-by: Robert Snow <[email protected]>
Co-authored-by: GitHub <[email protected]>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent ea24e97 commit 0ab792f
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 8 deletions.
63 changes: 56 additions & 7 deletions packages/@react-spectrum/s2/src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import {baseColor, focusRing, fontRelative, style} from '../style' with {type: 'macro'};
import {baseColor, focusRing, fontRelative, linearGradient, style} from '../style' with {type: 'macro'};
import {ButtonRenderProps, ContextValue, Link, LinkProps, OverlayTriggerStateContext, Provider, Button as RACButton, ButtonProps as RACButtonProps} from 'react-aria-components';
import {centerBaseline} from './CenterBaseline';
import {centerPadding, getAllowedOverrides, staticColor, StyleProps} from './style-utils' with {type: 'macro'};
Expand All @@ -34,7 +34,7 @@ interface ButtonStyleProps {
*
* @default 'primary'
*/
variant?: 'primary' | 'secondary' | 'accent' | 'negative',
variant?: 'primary' | 'secondary' | 'accent' | 'negative' | 'premium' | 'genai',
/**
* The background style of the Button.
*
Expand Down Expand Up @@ -102,6 +102,10 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
fillStyle: {
fill: 0,
outline: 2
},
variant: {
premium: 0,
genai: 0
}
},
'--labelPadding': {
Expand Down Expand Up @@ -134,18 +138,43 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
isDisabled: 'GrayText'
}
},
backgroundImage: {
variant: {
premium: {
default: linearGradient('96deg', ['fuchsia-900', 0], ['indigo-900', 66], ['blue-900', 100]),
isHovered: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100]),
isPressed: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100]),
isFocusVisible: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100])
},
genai: {
default: linearGradient('96deg', ['red-900', 0], ['magenta-900', 33], ['indigo-900', 100]),
isHovered: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100]),
isPressed: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100]),
isFocusVisible: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100])
}
},
isDisabled: 'none',
isPending: 'none',
forcedColors: 'none'
},
backgroundColor: {
fillStyle: {
fill: {
variant: {
primary: 'neutral',
secondary: baseColor('gray-100'),
accent: 'accent',
negative: 'negative'
negative: 'negative',
premium: 'gray-100',
genai: 'gray-100'
},
isDisabled: 'disabled'
},
outline: {
variant: {
premium: 'gray-100',
genai: 'gray-100'
},
default: 'transparent',
isHovered: 'gray-100',
isPressed: 'gray-100',
Expand All @@ -158,11 +187,17 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
fill: {
variant: {
primary: baseColor('transparent-overlay-800'),
secondary: baseColor('transparent-overlay-100')
secondary: baseColor('transparent-overlay-100'),
premium: 'gray-800',
genai: 'gray-800'
},
isDisabled: 'transparent-overlay-100'
},
outline: {
variant: {
premium: 'gray-800',
genai: 'gray-800'
},
default: 'transparent',
isHovered: 'transparent-overlay-100',
isPressed: 'transparent-overlay-100',
Expand All @@ -189,12 +224,18 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
primary: 'gray-25',
secondary: 'neutral',
accent: 'white',
negative: 'white'
negative: 'white',
premium: 'white',
genai: 'white'
},
isDisabled: 'disabled'
},
outline: {
default: 'neutral',
variant: {
premium: 'white',
genai: 'white'
},
isDisabled: 'disabled'
}
},
Expand All @@ -203,10 +244,18 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
fill: {
variant: {
primary: 'auto',
secondary: baseColor('transparent-overlay-800')
secondary: baseColor('transparent-overlay-800'),
premium: 'white',
genai: 'white'
}
},
outline: baseColor('transparent-overlay-800')
outline: {
variant: {
premium: 'white',
genai: 'white'
},
default: baseColor('transparent-overlay-800')
}
},
isDisabled: 'transparent-overlay-400'
},
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/s2/style/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

import {fontRelative as internalFontRelative, size as internalSize, space as internalSpace} from './spectrum-theme';
export {baseColor, edgeToText, lightDark, colorMix, style} from './spectrum-theme';
export {baseColor, edgeToText, lightDark, linearGradient, colorMix, style} from './spectrum-theme';
export type {StyleString} from './types';

// Wrap these functions in arbitrary value syntax when called from the outside.
Expand Down
4 changes: 4 additions & 0 deletions packages/@react-spectrum/s2/style/spectrum-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ export function colorMix(a: SpectrumColor, b: SpectrumColor, percent: number): `
return `[color-mix(in srgb, ${parseColor(a)}, ${parseColor(b)} ${percent}%)]`;
}

export function linearGradient(angle: string, ...tokens: [SpectrumColor, number][]): string {
return `linear-gradient(${angle}, ${tokens.map(([color, stop]) => `${parseColor(color)} ${stop}%`)})`;
}

function generateSpacing<K extends number[]>(px: K): {[P in K[number]]: string} {
let res: any = {};
for (let p of px) {
Expand Down

1 comment on commit 0ab792f

@rspbot
Copy link

@rspbot rspbot commented on 0ab792f Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.