Skip to content

Commit 59e9400

Browse files
committed
add subpage for reference and advanced style macro section
1 parent 980d3d6 commit 59e9400

File tree

5 files changed

+220
-205
lines changed

5 files changed

+220
-205
lines changed

packages/dev/s2-docs/pages/s2/styling.mdx

Lines changed: 1 addition & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ function YourComponent() {
119119

120120
## Values
121121

122-
The `style` macro supports a constrained set of values per property that conform to Spectrum 2. This improves consistency and maintainability.
122+
The `style` macro supports a constrained set of values per property that conform to Spectrum 2. This improves consistency and maintainability. See the [reference](./styling/reference.html) page for a full list of available style macro properties.
123123

124124
### Colors
125125

@@ -182,190 +182,6 @@ Define conditional values as objects to handle media queries, UI states (hover/p
182182

183183
Conditions are mutually exclusive and ordered. The macro uses CSS cascade layers so the last matching condition wins without specificity issues.
184184

185-
### Runtime conditions
186-
187-
When runtime conditions are detected (e.g., variants, UI states), the macro returns a function to resolve styles at runtime.
188-
189-
```tsx
190-
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
191-
192-
const styles = style({
193-
backgroundColor: {
194-
variant: {
195-
primary: 'accent',
196-
secondary: 'neutral'
197-
}
198-
}
199-
});
200-
201-
function MyComponent({variant}: {variant: 'primary' | 'secondary'}) {
202-
return <div className={styles({variant})} />
203-
}
204-
```
205-
206-
Boolean conditions starting with `is` or `allows` can be used directly without nesting:
207-
208-
```tsx
209-
const styles = style({
210-
backgroundColor: {
211-
default: 'gray-100',
212-
isSelected: 'gray-900',
213-
allowsRemoving: 'gray-400'
214-
}
215-
});
216-
217-
<div className={styles({isSelected: true})} />
218-
```
219-
220-
Runtime conditions work well with render props in React Aria Components. If you inline styles, you’ll get autocomplete for available conditions.
221-
222-
```tsx
223-
import {Checkbox} from 'react-aria-components';
224-
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
225-
226-
<Checkbox
227-
className={style({
228-
backgroundColor: {
229-
default: 'gray-100',
230-
isHovered: 'gray-200',
231-
isSelected: 'gray-900'
232-
}
233-
})}
234-
/>
235-
```
236-
237-
### Nesting conditions
238-
239-
Nest conditions to apply styles when multiple conditions are true. Conditions at the same level are mutually exclusive; order determines precedence.
240-
241-
```tsx
242-
const styles = style({
243-
backgroundColor: {
244-
default: 'gray-25',
245-
isSelected: {
246-
default: 'neutral',
247-
isEmphasized: 'accent',
248-
forcedColors: 'Highlight',
249-
isDisabled: {
250-
default: 'gray-400',
251-
forcedColors: 'GrayText'
252-
}
253-
}
254-
}
255-
});
256-
257-
<div className={styles({isSelected, isEmphasized, isDisabled})} />
258-
```
259-
260-
## Reusing styles
261-
262-
Extract common styles into constants and spread them into `style` calls. These must be in the same file or imported from another file as a macro.
263-
264-
```tsx
265-
const horizontalStack = {
266-
display: 'flex',
267-
alignItems: 'center',
268-
columnGap: 8
269-
} as const;
270-
271-
const styles = style({
272-
...horizontalStack,
273-
columnGap: 4
274-
});
275-
```
276-
277-
Create custom utilities by defining your own macros.
278-
279-
```ts
280-
// style-utils.ts
281-
export function horizontalStack(gap: number) {
282-
return {
283-
display: 'flex',
284-
alignItems: 'center',
285-
columnGap: gap
286-
} as const;
287-
}
288-
```
289-
290-
Usage:
291-
292-
```tsx
293-
// component.tsx
294-
import {horizontalStack} from './style-utils' with {type: 'macro'};
295-
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
296-
297-
const styles = style({
298-
...horizontalStack(4),
299-
backgroundColor: 'base'
300-
});
301-
```
302-
303-
### Built-in utilities
304-
305-
Use `focusRing()` to add the standard Spectrum focus ring.
306-
307-
```tsx
308-
"use client";
309-
import {style, focusRing} from '@react-spectrum/s2/style' with {type: 'macro'};
310-
import {Button} from '@react-spectrum/s2';
311-
312-
const buttonStyle = style({
313-
...focusRing(),
314-
// ...other styles
315-
});
316-
317-
<Button styles={buttonStyle}>Press me</Button>
318-
```
319-
320-
## Setting CSS variables
321-
322-
CSS variables can be directly defined in a `style` macro, allowing child elements to then access them in their own styles.
323-
A `type` should be provided to specify the CSS property type the `value` represents.
324-
325-
```tsx
326-
const parentStyle = style({
327-
'--rowBackgroundColor': {
328-
type: 'backgroundColor',
329-
value: 'gray-400'
330-
}
331-
});
332-
333-
const childStyle = style({
334-
backgroundColor: '--rowBackgroundColor'
335-
});
336-
```
337-
338-
## Creating custom components
339-
340-
In-depth examples are coming soon!
341-
342-
`mergeStyles` can be used to merge the style strings from multiple macros together, with the latter styles taking precedence similar to object spreading.
343-
This behavior can be leveraged to create a component API that allows an end user to only override specific styles conditionally.
344-
345-
```tsx
346-
// User can override the component's background color ONLY if it isn't "quiet"
347-
const baselineStyles = style({backgroundColor: 'gray-100'}, ['backgroundColor']);
348-
const quietStyles = style({backgroundColor: 'transparent'});
349-
const userStyles = style({backgroundColor: 'celery-600'});
350-
351-
function MyComponent({isQuiet, styles}: {isQuiet?: boolean, styles?: StyleString}) {
352-
let result = mergeStyles(
353-
baselineStyles(null, styles),
354-
isQuiet ? quietStyles : null
355-
);
356-
357-
return <div className={result}>My component</div>
358-
}
359-
360-
// Displays quiet styles
361-
<MyComponent isQuiet styles={userStyles} />
362-
363-
// Displays user overrides
364-
<MyComponent styles={userStyles} />
365-
```
366-
367-
The `iconStyle` macro should be used when styling Icons, see the [docs]((icons.html#iconstyle)) for more information.
368-
369185
## CSS optimization
370186

371187
The `style` macro relies on CSS bundling and minification for optimal output. Follow these best practices:
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import {Layout} from '../../../src/Layout';
2+
export default Layout;
3+
4+
export const tags = ['style', 'macro', 'spectrum', 'custom', 'advanced'];
5+
export const description = 'Style macro advanced usage guide';
6+
7+
# Advanced style macro usage
8+
9+
A guide to advanced use cases with the `style` macro.
10+
11+
## Runtime conditions
12+
13+
When runtime conditions are detected (e.g., variants, UI states), the macro returns a function to resolve styles at runtime.
14+
15+
```tsx
16+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
17+
18+
const styles = style({
19+
backgroundColor: {
20+
variant: {
21+
primary: 'accent',
22+
secondary: 'neutral'
23+
}
24+
}
25+
});
26+
27+
function MyComponent({variant}: {variant: 'primary' | 'secondary'}) {
28+
return <div className={styles({variant})} />
29+
}
30+
```
31+
32+
Boolean conditions starting with `is` or `allows` can be used directly without nesting:
33+
34+
```tsx
35+
const styles = style({
36+
backgroundColor: {
37+
default: 'gray-100',
38+
isSelected: 'gray-900',
39+
allowsRemoving: 'gray-400'
40+
}
41+
});
42+
43+
<div className={styles({isSelected: true})} />
44+
```
45+
46+
Runtime conditions work well with render props in React Aria Components. If you inline styles, you’ll get autocomplete for available conditions.
47+
48+
```tsx
49+
import {Checkbox} from 'react-aria-components';
50+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
51+
52+
<Checkbox
53+
className={style({
54+
backgroundColor: {
55+
default: 'gray-100',
56+
isHovered: 'gray-200',
57+
isSelected: 'gray-900'
58+
}
59+
})}
60+
/>
61+
```
62+
63+
### Nesting conditions
64+
65+
Nest conditions to apply styles when multiple conditions are true. Conditions at the same level are mutually exclusive; order determines precedence.
66+
67+
```tsx
68+
const styles = style({
69+
backgroundColor: {
70+
default: 'gray-25',
71+
isSelected: {
72+
default: 'neutral',
73+
isEmphasized: 'accent',
74+
forcedColors: 'Highlight',
75+
isDisabled: {
76+
default: 'gray-400',
77+
forcedColors: 'GrayText'
78+
}
79+
}
80+
}
81+
});
82+
83+
<div className={styles({isSelected, isEmphasized, isDisabled})} />
84+
```
85+
86+
## Reusing styles
87+
88+
Extract common styles into constants and spread them into `style` calls. These must be in the same file or imported from another file as a macro.
89+
90+
```tsx
91+
// style-utils.ts
92+
export const bannerBackground = () => 'blue-1000' as const;
93+
94+
// component.tsx
95+
import {bannerBackground} from './style-utils' with {type: 'macro'};
96+
const horizontalStack = {
97+
display: 'flex',
98+
alignItems: 'center',
99+
columnGap: 8
100+
} as const;
101+
102+
const styles = style({
103+
...horizontalStack,
104+
backgroundColor: bannerBackground(),
105+
columnGap: 4
106+
});
107+
```
108+
109+
Create custom utilities by defining your own macros.
110+
111+
```ts
112+
// style-utils.ts
113+
export function horizontalStack(gap: number) {
114+
return {
115+
display: 'flex',
116+
alignItems: 'center',
117+
columnGap: gap
118+
} as const;
119+
}
120+
```
121+
122+
Usage:
123+
124+
```tsx
125+
// component.tsx
126+
import {horizontalStack} from './style-utils' with {type: 'macro'};
127+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
128+
129+
const styles = style({
130+
...horizontalStack(4),
131+
backgroundColor: 'base'
132+
});
133+
```
134+
135+
### Built-in utilities
136+
137+
Use `focusRing()` to add the standard Spectrum focus ring.
138+
139+
```tsx
140+
"use client";
141+
import {style, focusRing} from '@react-spectrum/s2/style' with {type: 'macro'};
142+
import {Button} from '@react-spectrum/s2';
143+
144+
const buttonStyle = style({
145+
...focusRing(),
146+
// ...other styles
147+
});
148+
149+
<Button styles={buttonStyle}>Press me</Button>
150+
```
151+
152+
## Setting CSS variables
153+
154+
CSS variables can be directly defined in a `style` macro, allowing child elements to then access them in their own styles.
155+
A `type` should be provided to specify the CSS property type the `value` represents.
156+
157+
```tsx
158+
const parentStyle = style({
159+
'--rowBackgroundColor': {
160+
type: 'backgroundColor',
161+
value: 'gray-400'
162+
}
163+
});
164+
165+
const childStyle = style({
166+
backgroundColor: '--rowBackgroundColor'
167+
});
168+
```
169+
170+
## Creating custom components
171+
172+
In-depth examples are coming soon!
173+
174+
`mergeStyles` can be used to merge the style strings from multiple macros together, with the latter styles taking precedence similar to object spreading.
175+
This behavior can be leveraged to create a component API that allows an end user to only override specific styles conditionally.
176+
177+
```tsx
178+
// User can override the component's background color ONLY if it isn't "quiet"
179+
const baselineStyles = style({backgroundColor: 'gray-100'}, ['backgroundColor']);
180+
const quietStyles = style({backgroundColor: 'transparent'});
181+
const userStyles = style({backgroundColor: 'celery-600'});
182+
183+
function MyComponent({isQuiet, styles}: {isQuiet?: boolean, styles?: StyleString}) {
184+
let result = mergeStyles(
185+
baselineStyles(null, styles),
186+
isQuiet ? quietStyles : null
187+
);
188+
189+
return <div className={result}>My component</div>
190+
}
191+
192+
// Displays quiet styles
193+
<MyComponent isQuiet styles={userStyles} />
194+
195+
// Displays user overrides
196+
<MyComponent styles={userStyles} />
197+
```
198+
199+
The `iconStyle` macro should be used when styling Icons, see the [docs](../icons.html#iconstyle) for more information.

0 commit comments

Comments
 (0)