Skip to content

Commit a71fbed

Browse files
devongovettLFDanLu
andauthored
feat: Add staticColor="auto" variant (#7464)
* Add staticColor="auto" variant * Reduce generated CSS size * fix ts --------- Co-authored-by: Daniel Lu <[email protected]>
1 parent b82d0da commit a71fbed

19 files changed

+202
-243
lines changed

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

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {ButtonProps, ButtonRenderProps, ContextValue, OverlayTriggerStateContext
1717
import {centerBaseline} from './CenterBaseline';
1818
import {createContext, forwardRef, ReactNode, useContext} from 'react';
1919
import {FocusableRef, FocusableRefValue} from '@react-types/shared';
20-
import {getAllowedOverrides, StyleProps} from './style-utils' with { type: 'macro' };
20+
import {getAllowedOverrides, staticColor, StyleProps} from './style-utils' with { type: 'macro' };
2121
import {IconContext} from './Icon';
2222
import {pressScale} from './pressScale';
2323
import {SkeletonContext} from './Skeleton';
@@ -34,7 +34,7 @@ export interface ActionButtonStyleProps {
3434
*/
3535
size?: 'XS' | 'S' | 'M' | 'L' | 'XL',
3636
/** The static color style to apply. Useful when the ActionButton appears over a color background. */
37-
staticColor?: 'black' | 'white',
37+
staticColor?: 'black' | 'white' | 'auto',
3838
/** Whether the button should be displayed with a [quiet style](https://spectrum.adobe.com/page/action-button/#Quiet). */
3939
isQuiet?: boolean
4040
}
@@ -59,8 +59,9 @@ export interface ActionButtonProps extends Omit<ButtonProps, 'className' | 'styl
5959

6060
// These styles handle both ActionButton and ToggleButton
6161
const iconOnly = ':has([slot=icon], [slot=avatar]):not(:has([data-rsp-slot=text]))';
62-
export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & ToggleButtonStyleProps & ActionGroupItemStyleProps & {isInGroup: boolean}>({
62+
export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & ToggleButtonStyleProps & ActionGroupItemStyleProps & {isInGroup: boolean, isStaticColor: boolean}>({
6363
...focusRing(),
64+
...staticColor(),
6465
display: 'flex',
6566
alignItems: 'center',
6667
justifyContent: 'center',
@@ -98,33 +99,17 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
9899
isQuiet: 'transparent'
99100
}
100101
},
101-
staticColor: {
102-
white: {
103-
...baseColor('transparent-white-100'),
104-
default: {
105-
default: 'transparent-white-100',
106-
isQuiet: 'transparent'
107-
},
108-
isSelected: {
109-
default: baseColor('transparent-white-800'),
110-
isDisabled: {
111-
default: 'transparent-white-100',
112-
isQuiet: 'transparent'
113-
}
114-
}
102+
isStaticColor: {
103+
...baseColor('transparent-overlay-100'),
104+
default: {
105+
default: 'transparent-overlay-100',
106+
isQuiet: 'transparent'
115107
},
116-
black: {
117-
...baseColor('transparent-black-100'),
118-
default: {
119-
default: 'transparent-black-100',
108+
isSelected: {
109+
default: baseColor('transparent-overlay-800'),
110+
isDisabled: {
111+
default: 'transparent-overlay-100',
120112
isQuiet: 'transparent'
121-
},
122-
isSelected: {
123-
default: baseColor('transparent-black-800'),
124-
isDisabled: {
125-
default: 'transparent-black-100',
126-
isQuiet: 'transparent'
127-
}
128113
}
129114
}
130115
},
@@ -143,17 +128,10 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
143128
isEmphasized: 'white'
144129
},
145130
isDisabled: 'disabled',
146-
staticColor: {
147-
white: {
148-
default: baseColor('transparent-white-800'),
149-
isSelected: 'black',
150-
isDisabled: 'transparent-white-400'
151-
},
152-
black: {
153-
default: baseColor('transparent-black-800'),
154-
isSelected: 'white',
155-
isDisabled: 'transparent-black-400'
156-
}
131+
isStaticColor: {
132+
default: baseColor('transparent-overlay-800'),
133+
isSelected: 'auto',
134+
isDisabled: 'transparent-overlay-400'
157135
},
158136
forcedColors: {
159137
default: 'ButtonText',
@@ -169,10 +147,7 @@ export const btnStyles = style<ButtonRenderProps & ActionButtonStyleProps & Togg
169147
},
170148
outlineColor: {
171149
default: 'focus-ring',
172-
staticColor: {
173-
white: 'white',
174-
black: 'black'
175-
},
150+
isStaticColor: 'transparent-overlay-1000',
176151
forcedColors: 'Highlight'
177152
},
178153
borderStyle: 'none',
@@ -287,6 +262,7 @@ export const ActionButton = forwardRef(function ActionButton(props: ActionButton
287262
// Retain hover styles when an overlay is open.
288263
isHovered: renderProps.isHovered || overlayTriggerState?.isOpen || false,
289264
staticColor,
265+
isStaticColor: !!staticColor,
290266
size,
291267
isQuiet,
292268
density,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export interface ActionButtonGroupProps extends UnsafeStyles, SlotProps {
3636
/** Whether the buttons should divide the container width equally. */
3737
isJustified?: boolean,
3838
/** Whether the button should be displayed with an [emphasized style](https://spectrum.adobe.com/page/action-button/#Emphasis). */
39-
staticColor?: 'white' | 'black',
39+
staticColor?: 'white' | 'black' | 'auto',
4040
/**
4141
* The axis the group should align with.
4242
* @default 'horizontal'

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

Lines changed: 36 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import {baseColor, focusRing, fontRelative, 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';
16-
import {centerPadding, getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
16+
import {centerPadding, getAllowedOverrides, staticColor, StyleProps} from './style-utils' with {type: 'macro'};
1717
import {createContext, forwardRef, ReactNode, useContext, useEffect, useState} from 'react';
1818
import {FocusableRef, FocusableRefValue} from '@react-types/shared';
1919
import {IconContext} from './Icon';
@@ -48,7 +48,7 @@ interface ButtonStyleProps {
4848
*/
4949
size?: 'S' | 'M' | 'L' | 'XL',
5050
/** The static color style to apply. Useful when the Button appears over a color background. */
51-
staticColor?: 'white' | 'black'
51+
staticColor?: 'white' | 'black' | 'auto'
5252
}
5353

5454
export interface ButtonProps extends Omit<RACButtonProps, 'className' | 'style' | 'children' | 'onHover' | 'onHoverStart' | 'onHoverEnd' | 'onHoverChange'>, StyleProps, ButtonStyleProps {
@@ -65,8 +65,9 @@ export const ButtonContext = createContext<ContextValue<ButtonProps, FocusableRe
6565
export const LinkButtonContext = createContext<ContextValue<ButtonProps, FocusableRefValue<HTMLAnchorElement>>>(null);
6666

6767
const iconOnly = ':has([slot=icon]):not(:has([data-rsp-slot=text]))';
68-
const button = style<ButtonRenderProps & ButtonStyleProps>({
68+
const button = style<ButtonRenderProps & ButtonStyleProps & {isStaticColor: boolean}>({
6969
...focusRing(),
70+
...staticColor(),
7071
position: 'relative',
7172
display: 'flex',
7273
alignItems: {
@@ -120,21 +121,12 @@ const button = style<ButtonRenderProps & ButtonStyleProps>({
120121
secondary: baseColor('gray-300')
121122
},
122123
isDisabled: 'disabled',
123-
staticColor: {
124-
white: {
125-
variant: {
126-
primary: baseColor('transparent-white-800'),
127-
secondary: baseColor('transparent-white-300')
128-
},
129-
isDisabled: 'transparent-white-300'
124+
isStaticColor: {
125+
variant: {
126+
primary: baseColor('transparent-overlay-800'),
127+
secondary: baseColor('transparent-overlay-300')
130128
},
131-
black: {
132-
variant: {
133-
primary: baseColor('transparent-black-800'),
134-
secondary: baseColor('transparent-black-300')
135-
},
136-
isDisabled: 'transparent-black-300'
137-
}
129+
isDisabled: 'transparent-overlay-300'
138130
},
139131
forcedColors: {
140132
default: 'ButtonBorder',
@@ -161,41 +153,21 @@ const button = style<ButtonRenderProps & ButtonStyleProps>({
161153
isDisabled: 'transparent'
162154
}
163155
},
164-
staticColor: {
165-
white: {
166-
fillStyle: {
167-
fill: {
168-
variant: {
169-
primary: baseColor('transparent-white-800'),
170-
secondary: baseColor('transparent-white-100')
171-
},
172-
isDisabled: 'transparent-white-100'
173-
},
174-
outline: {
175-
default: 'transparent',
176-
isHovered: 'transparent-white-100',
177-
isPressed: 'transparent-white-100',
178-
isFocusVisible: 'transparent-white-100',
179-
isDisabled: 'transparent'
180-
}
181-
}
182-
},
183-
black: {
184-
fillStyle: {
185-
fill: {
186-
variant: {
187-
primary: baseColor('transparent-black-800'),
188-
secondary: baseColor('transparent-black-100')
189-
},
190-
isDisabled: 'transparent-black-100'
156+
isStaticColor: {
157+
fillStyle: {
158+
fill: {
159+
variant: {
160+
primary: baseColor('transparent-overlay-800'),
161+
secondary: baseColor('transparent-overlay-100')
191162
},
192-
outline: {
193-
default: 'transparent',
194-
isHovered: 'transparent-black-100',
195-
isPressed: 'transparent-black-100',
196-
isFocusVisible: 'transparent-black-100',
197-
isDisabled: 'transparent'
198-
}
163+
isDisabled: 'transparent-overlay-100'
164+
},
165+
outline: {
166+
default: 'transparent',
167+
isHovered: 'transparent-overlay-100',
168+
isPressed: 'transparent-overlay-100',
169+
isFocusVisible: 'transparent-overlay-100',
170+
isDisabled: 'transparent'
199171
}
200172
}
201173
},
@@ -226,31 +198,17 @@ const button = style<ButtonRenderProps & ButtonStyleProps>({
226198
isDisabled: 'disabled'
227199
}
228200
},
229-
staticColor: {
230-
white: {
231-
fillStyle: {
232-
fill: {
233-
variant: {
234-
primary: 'black',
235-
secondary: baseColor('transparent-white-800')
236-
}
237-
},
238-
outline: baseColor('transparent-white-800')
201+
isStaticColor: {
202+
fillStyle: {
203+
fill: {
204+
variant: {
205+
primary: 'auto',
206+
secondary: baseColor('transparent-overlay-800')
207+
}
239208
},
240-
isDisabled: 'transparent-white-400'
209+
outline: baseColor('transparent-overlay-800')
241210
},
242-
black: {
243-
fillStyle: {
244-
fill: {
245-
variant: {
246-
primary: 'white',
247-
secondary: baseColor('transparent-black-800')
248-
}
249-
},
250-
outline: baseColor('transparent-black-800')
251-
},
252-
isDisabled: 'transparent-black-400'
253-
}
211+
isDisabled: 'transparent-overlay-400'
254212
},
255213
forcedColors: {
256214
fillStyle: {
@@ -271,10 +229,7 @@ const button = style<ButtonRenderProps & ButtonStyleProps>({
271229
},
272230
outlineColor: {
273231
default: 'focus-ring',
274-
staticColor: {
275-
white: 'white',
276-
black: 'black'
277-
},
232+
isStaticColor: 'transparent-overlay-1000',
278233
forcedColors: 'Highlight'
279234
},
280235
forcedColorAdjust: 'none',
@@ -332,7 +287,8 @@ export const Button = forwardRef(function Button(props: ButtonProps, ref: Focusa
332287
variant,
333288
fillStyle,
334289
size,
335-
staticColor
290+
staticColor,
291+
isStaticColor: !!staticColor
336292
}, props.styles)}>
337293
<Provider
338294
values={[
@@ -419,6 +375,7 @@ export const LinkButton = forwardRef(function LinkButton(props: LinkButtonProps,
419375
fillStyle: props.fillStyle || 'fill',
420376
size: props.size || 'M',
421377
staticColor: props.staticColor,
378+
isStaticColor: !!props.staticColor,
422379
isPending: false
423380
}, props.styles)}>
424381
<Provider

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

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {Button, ButtonProps, ContextValue} from 'react-aria-components';
1515
import {createContext, forwardRef} from 'react';
1616
import CrossIcon from '../ui-icons/Cross';
1717
import {FocusableRef, FocusableRefValue} from '@react-types/shared';
18-
import {getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
18+
import {getAllowedOverrides, staticColor, StyleProps} from './style-utils' with {type: 'macro'};
1919
// @ts-ignore
2020
import intlMessages from '../intl/*.json';
2121
import {pressScale} from './pressScale';
@@ -31,19 +31,18 @@ export interface CloseButtonProps extends Pick<ButtonProps, 'isDisabled'>, Style
3131
*/
3232
size?: 'S' | 'M' | 'L' | 'XL',
3333
/** The static color style to apply. Useful when the Button appears over a color background. */
34-
staticColor?: 'white' | 'black'
34+
staticColor?: 'white' | 'black' | 'auto'
3535
}
3636

37+
// TODO(design): this is inconsistent with ActionButton
3738
const hoverBackground = {
3839
default: 'gray-100',
39-
staticColor: {
40-
white: 'transparent-white-100',
41-
black: 'transparent-black-100'
42-
}
40+
isStaticColor: 'transparent-overlay-100'
4341
} as const;
4442

4543
const styles = style({
4644
...focusRing(),
45+
...staticColor(),
4746
display: 'flex',
4847
alignItems: 'center',
4948
justifyContent: 'center',
@@ -64,24 +63,15 @@ const styles = style({
6463
value: {
6564
default: 'neutral',
6665
isDisabled: 'disabled',
67-
staticColor: {
68-
white: {
69-
default: baseColor('transparent-white-800'),
70-
isDisabled: 'transparent-white-400'
71-
},
72-
black: {
73-
default: baseColor('transparent-black-800'),
74-
isDisabled: 'transparent-black-400'
75-
}
66+
isStaticColor: {
67+
default: baseColor('transparent-overlay-800'),
68+
isDisabled: 'transparent-overlay-400'
7669
}
7770
}
7871
},
7972
outlineColor: {
8073
default: 'focus-ring',
81-
staticColor: {
82-
white: 'white',
83-
black: 'black'
84-
},
74+
isStaticColor: 'transparent-overlay-1000',
8575
forcedColors: 'Highlight'
8676
}
8777
}, getAllowedOverrides());
@@ -103,7 +93,7 @@ export const CloseButton = forwardRef(function CloseButton(props: CloseButtonPro
10393
slot="close"
10494
aria-label={stringFormatter.format('dialog.dismiss')}
10595
style={pressScale(domRef, UNSAFE_style)}
106-
className={renderProps => UNSAFE_className + styles({...renderProps, staticColor: props.staticColor}, props.styles)}>
96+
className={renderProps => UNSAFE_className + styles({...renderProps, staticColor: props.staticColor, isStaticColor: !!props.staticColor}, props.styles)}>
10797
<CrossIcon size={({S: 'L', M: 'XL', L: 'XXL', XL: 'XXXL'} as const)[props.size || 'M']} />
10898
</Button>
10999
);

0 commit comments

Comments
 (0)