Skip to content

Commit 34ad8cc

Browse files
committed
move reference out of subpage and merge styling page
1 parent 5084b6b commit 34ad8cc

File tree

4 files changed

+198
-289
lines changed

4 files changed

+198
-289
lines changed

packages/dev/s2-docs/pages/s2/styling/reference.mdx renamed to packages/dev/s2-docs/pages/s2/reference.mdx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import {Layout} from '../../../src/Layout';
1+
import {Layout} from '../../src/Layout';
22
import {InlineAlert, Heading, Content, Link} from '@react-spectrum/s2';
3-
import {S2Colors} from '../../../src/S2Colors';
4-
import {S2Typography} from '../../../src/S2Typography';
5-
import {StyleMacroProperties} from '../../../src/types';
6-
import {getPropertyDefinitions, getShorthandDefinitions} from '../../../src/styleProperties';
3+
import {S2Colors} from '../../src/S2Colors';
4+
import {S2Typography} from '../../src/S2Typography';
5+
import {StyleMacroProperties} from '../../src/types';
6+
import {getPropertyDefinitions, getShorthandDefinitions} from '../../src/styleProperties';
77
export default Layout;
88

9-
export const omitFromNav = true;
9+
export const section = 'Components';
1010
export const tags = ['style', 'macro', 'spectrum', 'custom', 'values', 'reference'];
1111
export const description = 'Reference table for the style macro';
1212

13-
# Style Macro Reference
13+
# Style Macro
1414

15-
Reference for the properties and values supported by React Spectrum `style` macro.
15+
The `style` macro supports a constrained set of values per property that conform to Spectrum 2.
1616

1717
## Colors
1818

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

Lines changed: 189 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
import {Layout} from '../../src/Layout';
22
import {InlineAlert, Heading, Content, Link} from '@react-spectrum/s2';
3-
import {S2Colors} from '../../src/S2Colors';
4-
import {S2Typography} from '../../src/S2Typography';
53
import {S2StyleProperties} from '../../src/S2StyleProperties';
64
import {S2FAQ} from '../../src/S2FAQ';
75
export default Layout;
86

97
export const section = 'Guides';
108
export const tags = ['style', 'macro', 'spectrum', 'custom'];
119
export const description = 'Styling in React Spectrum';
12-
export const relatedPages = [
13-
{title: 'Advanced', url: './styling/advanced.html'},
14-
{title: 'Reference Table', url: './styling/reference.html'}
15-
];
1610

1711
# Styling
1812

@@ -99,58 +93,214 @@ import {Button} from '@react-spectrum/s2';
9993
'visibility'
10094
]} />
10195

102-
## Values
96+
## Conditional styles
10397

104-
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.
98+
Define conditional values as objects to handle media queries, UI states (hover/press), and variants. This keeps all values for a property together.
99+
Note how the example below uses a predefined [breakpoint](./reference.html#conditions) alongside a custom media query.
105100

106-
### Colors
101+
```tsx
102+
<div
103+
className={style({
104+
padding: {
105+
default: 8,
106+
lg: 32,
107+
'@media (min-width: 2560px)': 64,
108+
}
109+
})}
110+
/>
111+
```
107112

108-
All Spectrum 2 color tokens are available across color properties (e.g., `backgroundColor`, `color`, `borderColor`).
113+
Conditions are mutually exclusive and ordered. The macro uses CSS cascade layers so the last matching condition wins without specificity issues.
109114

110-
<S2Colors />
115+
## Runtime conditions
111116

112-
### Spacing
117+
When runtime conditions are detected (e.g., variants, UI states), the macro returns a function to resolve styles at runtime.
113118

114-
Spacing props like `margin` and `padding` accept values on a **4px grid**. These are specified in `px` and get converted to `rem`. In addition to numbers, these named options are available:
119+
```tsx
120+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
115121

116-
- `edge-to-text` – default spacing between the edge of a control and its text. Relative to control height.
117-
- `pill` – default spacing between the edge of a pill-shaped control and its text. Relative to control height.
118-
- `text-to-control` – default spacing between text and a control (e.g., label and input). Scales with font size.
119-
- `text-to-visual` – default spacing between text and a visual element (e.g., icon). Scales with font size.
122+
const styles = style({
123+
backgroundColor: {
124+
variant: {
125+
primary: 'accent',
126+
secondary: 'neutral'
127+
}
128+
}
129+
});
120130

121-
### Sizing
131+
function MyComponent({variant}: {variant: 'primary' | 'secondary'}) {
132+
return <div className={styles({variant})} />
133+
}
134+
```
122135

123-
Size props like `width` and `height` accept arbitrary pixel values. Values are converted to `rem` and multiplied by 1.25x on touch devices to increase hit targets.
136+
Boolean conditions starting with `is` or `allows` can be used directly without nesting:
124137

125-
### Typography
138+
```tsx
139+
const styles = style({
140+
backgroundColor: {
141+
default: 'gray-100',
142+
isSelected: 'gray-900',
143+
allowsRemoving: 'gray-400'
144+
}
145+
});
146+
147+
<div className={styles({isSelected: true})} />
148+
```
126149

127-
Spectrum 2 typography is applied via the `font` shorthand, which sets `fontFamily`, `fontSize`, `fontWeight`, `lineHeight`, and `color`. You can override any of these individually.
128-
Note that you should always specify the `font` at the element level, setting it globally is insufficient since this will often differ per component.
150+
Runtime conditions work well with render props in React Aria Components. If you inline styles, you’ll get autocomplete for available conditions.
129151

130152
```tsx
131-
<main>
132-
<h1 className={style({font: 'heading-xl'})}>Heading</h1>
133-
<p className={style({font: 'body'})}>Body</p>
134-
<ul className={style({font: 'body-sm', fontWeight: 'bold'})}>
135-
<li>List item</li>
136-
</ul>
137-
</main>
153+
import {Checkbox} from 'react-aria-components';
154+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
155+
156+
<Checkbox
157+
className={style({
158+
backgroundColor: {
159+
default: 'gray-100',
160+
isHovered: 'gray-200',
161+
isSelected: 'gray-900'
162+
}
163+
})}
164+
/>
138165
```
139166

140-
Type scales include: UI, Body, Heading, Title, Detail, and Code. Each scale has a default and additional t-shirt sizes (e.g., `ui-sm`, `heading-2xl`, `code-xl`).
167+
### Nesting conditions
141168

142-
<S2Typography />
169+
Nest conditions to apply styles when multiple conditions are true. Conditions at the same level are mutually exclusive; order determines precedence.
143170

144-
<InlineAlert variant="notice">
145-
<Heading>Important Note</Heading>
146-
<Content>
147-
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.
148-
</Content>
149-
</InlineAlert>
171+
```tsx
172+
const styles = style({
173+
backgroundColor: {
174+
default: 'gray-25',
175+
isSelected: {
176+
default: 'neutral',
177+
isEmphasized: 'accent',
178+
forcedColors: 'Highlight',
179+
isDisabled: {
180+
default: 'gray-400',
181+
forcedColors: 'GrayText'
182+
}
183+
}
184+
}
185+
});
186+
187+
<div className={styles({isSelected, isEmphasized, isDisabled})} />
188+
```
189+
190+
## Reusing styles
191+
192+
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.
193+
194+
```tsx
195+
// style-utils.ts
196+
export const bannerBackground = () => 'blue-1000' as const;
197+
198+
// component.tsx
199+
import {bannerBackground} from './style-utils' with {type: 'macro'};
200+
const horizontalStack = {
201+
display: 'flex',
202+
alignItems: 'center',
203+
columnGap: 8
204+
} as const;
205+
206+
const styles = style({
207+
...horizontalStack,
208+
backgroundColor: bannerBackground(),
209+
columnGap: 4
210+
});
211+
```
212+
213+
Create custom utilities by defining your own macros.
214+
215+
```ts
216+
// style-utils.ts
217+
export function horizontalStack(gap: number) {
218+
return {
219+
display: 'flex',
220+
alignItems: 'center',
221+
columnGap: gap
222+
} as const;
223+
}
224+
```
225+
226+
Usage:
227+
228+
```tsx
229+
// component.tsx
230+
import {horizontalStack} from './style-utils' with {type: 'macro'};
231+
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
232+
233+
const styles = style({
234+
...horizontalStack(4),
235+
backgroundColor: 'base'
236+
});
237+
```
238+
239+
### Built-in utilities
240+
241+
Use `focusRing()` to add the standard Spectrum focus ring.
242+
243+
```tsx
244+
"use client";
245+
import {style, focusRing} from '@react-spectrum/s2/style' with {type: 'macro'};
246+
import {Button} from '@react-spectrum/s2';
247+
248+
const buttonStyle = style({
249+
...focusRing(),
250+
// ...other styles
251+
});
252+
253+
<Button styles={buttonStyle}>Press me</Button>
254+
```
150255

151-
### Breakpoints
256+
## Setting CSS variables
257+
258+
CSS variables can be directly defined in a `style` macro, allowing child elements to then access them in their own styles.
259+
A `type` should be provided to specify the CSS property type the `value` represents.
260+
261+
```tsx
262+
const parentStyle = style({
263+
'--rowBackgroundColor': {
264+
type: 'backgroundColor',
265+
value: 'gray-400'
266+
}
267+
});
268+
269+
const childStyle = style({
270+
backgroundColor: '--rowBackgroundColor'
271+
});
272+
```
273+
274+
## Creating custom components
275+
276+
In-depth examples are coming soon!
277+
278+
`mergeStyles` can be used to merge the style strings from multiple macros together, with the latter styles taking precedence similar to object spreading.
279+
This behavior can be leveraged to create a component API that allows an end user to only override specific styles conditionally.
280+
281+
```tsx
282+
// User can override the component's background color ONLY if it isn't "quiet"
283+
const baselineStyles = style({backgroundColor: 'gray-100'}, ['backgroundColor']);
284+
const quietStyles = style({backgroundColor: 'transparent'});
285+
const userStyles = style({backgroundColor: 'celery-600'});
286+
287+
function MyComponent({isQuiet, styles}: {isQuiet?: boolean, styles?: StyleString}) {
288+
let result = mergeStyles(
289+
baselineStyles(null, styles),
290+
isQuiet ? quietStyles : null
291+
);
292+
293+
return <div className={result}>My component</div>
294+
}
295+
296+
// Displays quiet styles
297+
<MyComponent isQuiet styles={userStyles} />
298+
299+
// Displays user overrides
300+
<MyComponent styles={userStyles} />
301+
```
152302

153-
The style macro has several predefined [breakpoints](./styling/reference.html#conditions), but you can use arbitrary CSS media or container queries as [conditional values](./styling/advanced.html#conditional-styles) in your style macro as well.
303+
The `iconStyle` macro should be used when styling Icons, see the [docs](./Icons.html#iconstyle) for more information.
154304

155305
## CSS optimization
156306

0 commit comments

Comments
 (0)