Skip to content

Commit 0ab792f

Browse files
jluyausnowystinger
andauthored
feat: add gradient variants to Button (#7514)
* 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]>
1 parent ea24e97 commit 0ab792f

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

packages/@react-spectrum/s2/src/Button.tsx

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import {baseColor, focusRing, fontRelative, style} from '../style' with {type: 'macro'};
13+
import {baseColor, focusRing, fontRelative, linearGradient, style} from '../style' with {type: 'macro'};
1414
import {ButtonRenderProps, ContextValue, Link, LinkProps, OverlayTriggerStateContext, Provider, Button as RACButton, ButtonProps as RACButtonProps} from 'react-aria-components';
1515
import {centerBaseline} from './CenterBaseline';
1616
import {centerPadding, getAllowedOverrides, staticColor, StyleProps} from './style-utils' with {type: 'macro'};
@@ -34,7 +34,7 @@ interface ButtonStyleProps {
3434
*
3535
* @default 'primary'
3636
*/
37-
variant?: 'primary' | 'secondary' | 'accent' | 'negative',
37+
variant?: 'primary' | 'secondary' | 'accent' | 'negative' | 'premium' | 'genai',
3838
/**
3939
* The background style of the Button.
4040
*
@@ -102,6 +102,10 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
102102
fillStyle: {
103103
fill: 0,
104104
outline: 2
105+
},
106+
variant: {
107+
premium: 0,
108+
genai: 0
105109
}
106110
},
107111
'--labelPadding': {
@@ -134,18 +138,43 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
134138
isDisabled: 'GrayText'
135139
}
136140
},
141+
backgroundImage: {
142+
variant: {
143+
premium: {
144+
default: linearGradient('96deg', ['fuchsia-900', 0], ['indigo-900', 66], ['blue-900', 100]),
145+
isHovered: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100]),
146+
isPressed: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100]),
147+
isFocusVisible: linearGradient('96deg', ['fuchsia-1000', 0], ['indigo-1000', 66], ['blue-1000', 100])
148+
},
149+
genai: {
150+
default: linearGradient('96deg', ['red-900', 0], ['magenta-900', 33], ['indigo-900', 100]),
151+
isHovered: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100]),
152+
isPressed: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100]),
153+
isFocusVisible: linearGradient('96deg', ['red-1000', 0], ['magenta-1000', 33], ['indigo-1000', 100])
154+
}
155+
},
156+
isDisabled: 'none',
157+
isPending: 'none',
158+
forcedColors: 'none'
159+
},
137160
backgroundColor: {
138161
fillStyle: {
139162
fill: {
140163
variant: {
141164
primary: 'neutral',
142165
secondary: baseColor('gray-100'),
143166
accent: 'accent',
144-
negative: 'negative'
167+
negative: 'negative',
168+
premium: 'gray-100',
169+
genai: 'gray-100'
145170
},
146171
isDisabled: 'disabled'
147172
},
148173
outline: {
174+
variant: {
175+
premium: 'gray-100',
176+
genai: 'gray-100'
177+
},
149178
default: 'transparent',
150179
isHovered: 'gray-100',
151180
isPressed: 'gray-100',
@@ -158,11 +187,17 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
158187
fill: {
159188
variant: {
160189
primary: baseColor('transparent-overlay-800'),
161-
secondary: baseColor('transparent-overlay-100')
190+
secondary: baseColor('transparent-overlay-100'),
191+
premium: 'gray-800',
192+
genai: 'gray-800'
162193
},
163194
isDisabled: 'transparent-overlay-100'
164195
},
165196
outline: {
197+
variant: {
198+
premium: 'gray-800',
199+
genai: 'gray-800'
200+
},
166201
default: 'transparent',
167202
isHovered: 'transparent-overlay-100',
168203
isPressed: 'transparent-overlay-100',
@@ -189,12 +224,18 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
189224
primary: 'gray-25',
190225
secondary: 'neutral',
191226
accent: 'white',
192-
negative: 'white'
227+
negative: 'white',
228+
premium: 'white',
229+
genai: 'white'
193230
},
194231
isDisabled: 'disabled'
195232
},
196233
outline: {
197234
default: 'neutral',
235+
variant: {
236+
premium: 'white',
237+
genai: 'white'
238+
},
198239
isDisabled: 'disabled'
199240
}
200241
},
@@ -203,10 +244,18 @@ const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: bool
203244
fill: {
204245
variant: {
205246
primary: 'auto',
206-
secondary: baseColor('transparent-overlay-800')
247+
secondary: baseColor('transparent-overlay-800'),
248+
premium: 'white',
249+
genai: 'white'
207250
}
208251
},
209-
outline: baseColor('transparent-overlay-800')
252+
outline: {
253+
variant: {
254+
premium: 'white',
255+
genai: 'white'
256+
},
257+
default: baseColor('transparent-overlay-800')
258+
}
210259
},
211260
isDisabled: 'transparent-overlay-400'
212261
},

packages/@react-spectrum/s2/style/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

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

1717
// Wrap these functions in arbitrary value syntax when called from the outside.

packages/@react-spectrum/s2/style/spectrum-theme.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ export function colorMix(a: SpectrumColor, b: SpectrumColor, percent: number): `
111111
return `[color-mix(in srgb, ${parseColor(a)}, ${parseColor(b)} ${percent}%)]`;
112112
}
113113

114+
export function linearGradient(angle: string, ...tokens: [SpectrumColor, number][]): string {
115+
return `linear-gradient(${angle}, ${tokens.map(([color, stop]) => `${parseColor(color)} ${stop}%`)})`;
116+
}
117+
114118
function generateSpacing<K extends number[]>(px: K): {[P in K[number]]: string} {
115119
let res: any = {};
116120
for (let p of px) {

0 commit comments

Comments
 (0)