You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
React Spectrum includes a build-time style macro that generates atomic CSS and lets you apply Spectrum tokens directly in your components with type-safe autocompletion.
14
+
React Spectrum includes a build-time `style` macro that generates atomic CSS and lets you apply Spectrum tokens directly in your components with type-safe autocompletion.
15
15
16
16
## Style macro
17
17
@@ -37,6 +37,14 @@ Colocating styles with your component code means:
37
37
- Develop more efficiently – no switching files or writing selectors.
38
38
- Refactor with confidence – changes are isolated; deleting a component removes its styles.
39
39
40
+
<InlineAlertvariant="informative">
41
+
<Heading>Important Note</Heading>
42
+
<Content>
43
+
Due to the atomic nature of the generated CSS rules, it is strongly recommended that you follow the best practices listed [below](#css-optimization).
44
+
Failure to do so can result in large number of duplicate rules and obtuse styling bugs.
45
+
</Content>
46
+
</InlineAlert>
47
+
40
48
## Spectrum components
41
49
42
50
The `styles` prop accepts a limited set of CSS properties, including layout, spacing, sizing, and positioning. Other styles such as colors and internal padding cannot be customized within Spectrum components.
@@ -88,7 +96,7 @@ import {Button} from '@react-spectrum/s2';
88
96
89
97
### UNSAFE Style Overrides
90
98
91
-
We highly discourage overriding the styles of React Spectrum components because it may break at any time when we change our implementation, making it difficult for you to update in the future. Consider using [React Aria Components](https://react-spectrum.adobe.com/react-aria/) with our style macro to build a custom component with Spectrum styles instead.
99
+
We highly discourage overriding the styles of React Spectrum components because it may break at any time when we change our implementation, making it difficult for you to update in the future. Consider using [React Aria Components](https://react-spectrum.adobe.com/react-aria/) with our `style` macro to build a custom component with Spectrum styles instead.
92
100
93
101
With that being said, the `UNSAFE_className` and `UNSAFE_style` props are supported on Spectrum 2 components as last-resort escape hatches.
94
102
@@ -153,7 +161,7 @@ Type scales include: UI, Body, Heading, Title, Detail, and Code. Each scale has
153
161
<InlineAlertvariant="notice">
154
162
<Heading>Important Note</Heading>
155
163
<Content>
156
-
Only use `<Heading>` and `<Text>` inside Spectrum components with predefined styles (e.g., `<Dialog>`, `<MenuItem>`). They are unstyled by default and should not be used standalone. Use HTML elements with the style macro instead.
164
+
Only use `<Heading>` and `<Text>` inside Spectrum components with predefined styles (e.g., `<Dialog>`, `<MenuItem>`). They are unstyled by default and should not be used standalone. Use HTML elements with the `style` macro instead.
Boolean conditions starting with `is` can be used directly without nesting:
206
+
Boolean conditions starting with `is`or `allows`can be used directly without nesting:
199
207
200
208
```tsx
201
209
const styles =style({
202
210
backgroundColor: {
203
211
default: 'gray-100',
204
-
isSelected: 'gray-900'
212
+
isSelected: 'gray-900',
213
+
allowsRemoving: 'gray-400'
205
214
}
206
215
});
207
216
@@ -222,7 +231,7 @@ import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
222
231
isSelected: 'gray-900'
223
232
}
224
233
})}
225
-
/>
234
+
/>
226
235
```
227
236
228
237
### Nesting conditions
@@ -308,9 +317,31 @@ const buttonStyle = style({
308
317
<Buttonstyles={buttonStyle}>Press me</Button>
309
318
```
310
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 with style macros
339
+
340
+
TODO: I want to add the usuage of mergeStyles here from that one thread. Maybe an example with RAC + style macros as well
341
+
311
342
## CSS optimization
312
343
313
-
The style macro relies on CSS bundling and minification for optimal output. Follow these best practices:
344
+
The `style` macro relies on CSS bundling and minification for optimal output. Follow these best practices:
314
345
315
346
- Ensure styles are extracted into a CSS bundle; do not inject at runtime with `<style>` tags.
316
347
- Use a CSS minifier like `lightningcss` to deduplicate common rules (consider in dev for easier debugging).
@@ -362,4 +393,46 @@ CSS resets are strongly discouraged. Global CSS selectors can unintentionally af
362
393
/* App.css */
363
394
@layer reset, _;
364
395
@import"reset.css" layer(reset);
365
-
```
396
+
```
397
+
398
+
### Developing with style macros
399
+
400
+
Since `style` macros are quite different from using `className`/`style` directly, many may find it initially challenging to debug and develop against.
401
+
Below are some useful tools that may benefit your developer experience:
402
+
403
+
- The [atomic-css-devtools](https://github.com/astahmer/atomic-css-devtools) extension presents an inspected element's atomic CSS rules
404
+
in a non-atomic format, making it easier to scan.
405
+
406
+
- This [sandbox](https://codesandbox.io/p/devbox/react-spectrum-s2-style-macro-template-h6fpsq) is preconfigured to support React Spectrum S2, React Aria Components, and
407
+
the `style` macros for quick prototyping.
408
+
409
+
- If you are using Cursor, we offer a set of [Cursor rules](https://github.com/adobe/react-spectrum/blob/main/rules/style-macro.mdc) to use when developing with style macros. Additionally,
410
+
we have MCP servers for [React Aria](#TODO) and [React Spectrum](https://www.npmjs.com/package/@react-spectrum/mcp) respectively that interface with the docs.
411
+
412
+
413
+
- TODO: link to the dev tool Rob is making, perhaps replacing the atomic css dev tool. Any others we wanna call out
414
+
415
+
416
+
## FAQ
417
+
418
+
> I'm getting a "Could not statically evaluate macro argument" error.
419
+
420
+
This happens if your `style` macro has a condition that isn't evaluable at build time. This can happen for a variety of reasons such
421
+
as if you've referenced non-constant variables within your `style` macro or if you've called non-macro functions within your `style` macro.
422
+
If you are using Typescript, it can be as simple as forgetting to add `as const` to your own defined reusable macro.
423
+
TODO: create an example here, should I link to the sections above like "reusing styles"?
424
+
425
+
> I'm seeing a ton of duplicate rules being generated and/or my dev tools are very slow.
426
+
427
+
Please make sure you've followed the [best practices listed above](#css-optimization).
428
+
429
+
> I tried to pass my `style` macro to `UNSAFE_className` but it doesn't work.
430
+
431
+
The `style` macro is not meant to be used with `UNSAFE_className`. Overrides to the Spectrum styles is highly discouraged,
432
+
consider styling an equivalent React Aria Component instead.
433
+
TODO: we already touch on this via the UNSAFE Style Overrides section
434
+
TODO: example of RAC + style macros? maybe later
435
+
436
+
> I'm coming from S1, but where are Flex/Grid/etc?
437
+
438
+
These no longer exist. Please style `<div>`, `<span>`, and other standard HTML elements with the `style` macro instead.
0 commit comments