@fusion.dev/helix-docs 0.104.0 → 0.105.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/accessibility.mdx +92 -71
- package/content/angular.mdx +26 -24
- package/content/browser-support.mdx +61 -58
- package/content/building-on-the-headless-tier.mdx +100 -74
- package/content/charting.mdx +98 -79
- package/content/coding-agents.mdx +87 -69
- package/content/color-modes.mdx +40 -37
- package/content/color.mdx +67 -54
- package/content/composition.mdx +85 -83
- package/content/elevation-and-material.mdx +32 -29
- package/content/events.mdx +77 -65
- package/content/forms.mdx +69 -58
- package/content/iconography.mdx +75 -71
- package/content/installation.mdx +77 -68
- package/content/intent-reference.mdx +59 -54
- package/content/introduction.mdx +25 -23
- package/content/localization.mdx +122 -82
- package/content/maps.mdx +222 -0
- package/content/metrics.mdx +294 -297
- package/content/motion.mdx +44 -36
- package/content/other-frameworks.mdx +33 -31
- package/content/overlays.mdx +72 -54
- package/content/overriding-a-component.mdx +85 -74
- package/content/react.mdx +72 -64
- package/content/recipes.mdx +64 -47
- package/content/routing.mdx +100 -93
- package/content/sandbox.mdx +39 -39
- package/content/server-rendering.mdx +95 -84
- package/content/shape-and-borders.mdx +44 -37
- package/content/size-and-density.mdx +51 -46
- package/content/space-and-size.mdx +41 -34
- package/content/state-and-control.mdx +63 -51
- package/content/surfaces-and-separation.mdx +55 -53
- package/content/svelte.mdx +20 -19
- package/content/theme-builder.mdx +42 -31
- package/content/theming.mdx +58 -51
- package/content/tiers.mdx +69 -61
- package/content/tokens.mdx +72 -53
- package/content/typography.mdx +47 -47
- package/content/using-helix-with-an-agent.mdx +147 -115
- package/content/using-the-elements.mdx +55 -50
- package/content/versioning.mdx +42 -35
- package/content/visual-axes.mdx +168 -146
- package/content/vue.mdx +24 -24
- package/content/without-a-bundler.mdx +40 -23
- package/dist/pages.generated.js +49 -43
- package/dist/sources.generated.js +3337 -2680
- package/package.json +3 -3
package/content/react.mdx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The typings, the hydration bridge, and how state moves.
|
|
2
|
+
description: The React typings, the hydration bridge, and how state moves between React and the elements.
|
|
3
3
|
parent: installation
|
|
4
4
|
section: Getting started
|
|
5
5
|
title: React
|
|
@@ -7,17 +7,17 @@ title: React
|
|
|
7
7
|
|
|
8
8
|
# React
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
runtime bridge in `@fusion.dev/helix-core` that repairs two React behaviors.
|
|
10
|
+
The elements are custom elements, and React renders them directly, so there is
|
|
11
|
+
no React package. For React, we ship a `jsx.d.ts` file that types every tag, and
|
|
12
|
+
a runtime bridge in `@fusion.dev/helix-core` that repairs two React behaviors.
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
15
|
import '@fusion.dev/helix/jsx'
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
Add this types-only import once, anywhere TypeScript sees it. `<helix-button>`
|
|
19
|
+
then has typed props, and a value the component does not accept is a compile
|
|
20
|
+
error.
|
|
21
21
|
|
|
22
22
|
## Bind events with `onhelix-*`
|
|
23
23
|
|
|
@@ -25,25 +25,30 @@ component does not accept is a compile error rather than a runtime shrug.
|
|
|
25
25
|
<helix-accordion-item onhelix-before-open={(event) => track(event.detail.open)} />
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
The prop is `on`
|
|
29
|
-
React 19
|
|
30
|
-
written, so
|
|
28
|
+
The prop is `on` followed by the exact event name. `onHelixOpen` and `onOpen` do
|
|
29
|
+
not work. React 19 passes an unknown `on*` prop to `addEventListener` with the
|
|
30
|
+
name as written, so use the event's own casing.
|
|
31
31
|
|
|
32
|
-
## The bridge
|
|
32
|
+
## The hydration bridge
|
|
33
33
|
|
|
34
|
-
React skips everything it would have to apply imperatively
|
|
35
|
-
|
|
34
|
+
While React hydrates, it skips everything it would have to apply imperatively.
|
|
35
|
+
That affects two things, and `HelixElement` repairs both.
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
never bound, so an event fired before the next render finds nothing listening.
|
|
39
|
-
The element reads React's own stash off the node and binds what it finds, so a
|
|
40
|
-
handler works from the first paint rather than from the first re-render.
|
|
37
|
+
### Event handlers
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
React stores the event handlers it sees during hydration on the DOM node, but it
|
|
40
|
+
does not bind them. An event fired before the next render reaches no listener.
|
|
41
|
+
The element reads the handlers React stored on the node and binds them, so a
|
|
42
|
+
handler works from the first paint.
|
|
43
|
+
|
|
44
|
+
### Object and function properties
|
|
45
|
+
|
|
46
|
+
React drops object and function properties on both sides. The server renderer
|
|
47
|
+
writes nothing for a prop whose value is an object, and hydration never applies
|
|
48
|
+
one. An array prop therefore never reaches the element, and because the server
|
|
49
|
+
and the client agree, React shows no warning. The element assigns these
|
|
50
|
+
properties itself once it upgrades, so a data table can take its rows as a plain
|
|
51
|
+
prop:
|
|
47
52
|
|
|
48
53
|
```tsx
|
|
49
54
|
<helix-data-table label="People" rows={rows}>
|
|
@@ -53,41 +58,43 @@ upgrades, which is what lets a data table take its rows as a plain prop:
|
|
|
53
58
|
</helix-data-table>
|
|
54
59
|
```
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
The element assigns only properties the component declares, and only values an
|
|
62
|
+
attribute cannot carry. Strings still go through attributes, which already work.
|
|
63
|
+
The element also leaves a `null` alone, so the component keeps its default.
|
|
64
|
+
|
|
65
|
+
The columns are elements for the same reason. `field`, `sortable`, and `width`
|
|
66
|
+
are strings and booleans, so they pass through server rendering intact. `cell`
|
|
67
|
+
and `compare` are functions, set on an element that repairs its own props.
|
|
68
|
+
Inside a `columns` array, the bridge could not reach them.
|
|
59
69
|
|
|
60
|
-
The
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
The cell values still do not render on the server. That is a separate limit.
|
|
71
|
+
Reading a cell needs the columns, and the server render does not pass the table
|
|
72
|
+
its markup children. The first paint shows a labeled table with no data in
|
|
73
|
+
either case. Use `helix-table` when the content must be in the served HTML.
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
this one. Reading a cell needs the columns, and the columns are markup children
|
|
67
|
-
the server render does not hand the table, so the first paint is a labeled shell
|
|
68
|
-
either way. Use `helix-table` where the content has to be in the served HTML.
|
|
75
|
+
### The React version
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
The bridge is runtime code in `@fusion.dev/helix-core`, which you already have,
|
|
78
|
+
and it needs no configuration. It reads a React internal: the per-page key that
|
|
79
|
+
React stores props under. If a React release renames that key, the bridge stops
|
|
80
|
+
repairing, and your handlers again need a commit before they fire. We pin the
|
|
81
|
+
React version we measured the bridge against, and our build fails when React
|
|
82
|
+
moves past it, so a rename cannot go unnoticed.
|
|
76
83
|
|
|
77
|
-
##
|
|
84
|
+
## Seed, mirror, or refuse a value
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
Helix differs from React in one way that surprises people. This markup
|
|
87
|
+
compiles, and the field stays editable:
|
|
81
88
|
|
|
82
89
|
```tsx
|
|
83
|
-
//
|
|
90
|
+
// Compiles, and the field stays editable.
|
|
84
91
|
<helix-input label="Name" value="Ada" />
|
|
85
92
|
```
|
|
86
93
|
|
|
87
94
|
In React, `value` on a native `<input>` without `onChange` renders a read-only
|
|
88
|
-
field and
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
field and logs a warning. On a Helix element, `value` is a seed. The element
|
|
96
|
+
starts with that value and keeps applying its own changes, so the markup below
|
|
97
|
+
works without a handler.
|
|
91
98
|
|
|
92
99
|
```tsx
|
|
93
100
|
// Seeded: the element owns it from there.
|
|
@@ -107,17 +114,18 @@ handler beside it.
|
|
|
107
114
|
/>
|
|
108
115
|
```
|
|
109
116
|
|
|
110
|
-
**
|
|
111
|
-
a native `<input>` whose state did not
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
**To refuse a change, call `preventDefault()`.** Skipping `setState` does not
|
|
118
|
+
refuse it. React restores a native `<input>` whose state did not change, and it
|
|
119
|
+
does not do this for a custom element. A handler that does not call `setState`
|
|
120
|
+
leaves the element with the new value.
|
|
114
121
|
|
|
115
|
-
*Until 26
|
|
116
|
-
it
|
|
117
|
-
|
|
118
|
-
handler
|
|
122
|
+
*Until August 26, 2026, this page described the opposite behavior, and the typings
|
|
123
|
+
enforced it. Writing `value` made you the owner of the state. The element
|
|
124
|
+
applied no change until you set the value, and `<helix-input value="Ada" />`
|
|
125
|
+
without a handler was a compile error. We removed that mode and its
|
|
126
|
+
constraint.*
|
|
119
127
|
|
|
120
|
-
See [State and control](./state-and-control) for the
|
|
128
|
+
See [State and control](./state-and-control) for the full model.
|
|
121
129
|
|
|
122
130
|
## Register in a client component
|
|
123
131
|
|
|
@@ -129,16 +137,16 @@ export const HelixElements = () => null
|
|
|
129
137
|
```
|
|
130
138
|
|
|
131
139
|
Render it once in your layout. **Your pages stay server components.** An
|
|
132
|
-
unregistered tag is an unknown element in the HTML
|
|
133
|
-
definition
|
|
140
|
+
unregistered tag is an unknown element in the HTML, and it upgrades when the
|
|
141
|
+
definition loads. Your server components need no changes.
|
|
134
142
|
|
|
135
143
|
## Server components get no declarative shadow DOM
|
|
136
144
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
React inserts a server component's output by replaying the flight payload
|
|
146
|
+
through DOM APIs. The browser does not parse that output as HTML, and
|
|
147
|
+
declarative shadow DOM cannot activate for nodes inserted by script.
|
|
148
|
+
`elements.css` exists for this case. It styles the markup before the elements
|
|
149
|
+
upgrade, so the page looks finished before hydration.
|
|
142
150
|
|
|
143
|
-
[Server rendering](./server-rendering)
|
|
144
|
-
[Using the elements](./using-the-elements)
|
|
151
|
+
[Server rendering](./server-rendering) covers server rendering in full, and
|
|
152
|
+
[Using the elements](./using-the-elements) covers the other binding rules.
|
package/content/recipes.mdx
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Style your own HTML with Helix data attributes and no JavaScript.
|
|
3
3
|
section: Foundations
|
|
4
4
|
title: Recipes
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Recipes
|
|
8
8
|
|
|
9
|
-
`@fusion.dev/helix-styles`
|
|
10
|
-
|
|
11
|
-
They are `data-` attributes, they need no JavaScript, and they read the same
|
|
12
|
-
tokens the components do.
|
|
9
|
+
`@fusion.dev/helix-styles` includes recipes for markup that the components do
|
|
10
|
+
not render, such as:
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
- your own anchors
|
|
13
|
+
- your own buttons
|
|
14
|
+
- a card you built yourself
|
|
15
|
+
- prose from a CMS
|
|
16
|
+
|
|
17
|
+
Recipes are `data-` attributes. They need no JavaScript, and they use the same
|
|
18
|
+
tokens as the components. With recipes, your page can look like Helix without
|
|
19
|
+
any custom elements.
|
|
15
20
|
|
|
16
21
|
## Buttons
|
|
17
22
|
|
|
@@ -26,14 +31,18 @@ This is what lets a page look like Helix without a single custom element on it.
|
|
|
26
31
|
>Settings</a>
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
A button recipe has two axes:
|
|
35
|
+
|
|
36
|
+
- `data-button` sets the button's emphasis: `solid`, `outlined`, `ghost`, or
|
|
37
|
+
`subtle`.
|
|
38
|
+
- `data-button-tone` sets what the button means: `primary`, `accent`,
|
|
39
|
+
`neutral`, or `danger`.
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
the recipe
|
|
36
|
-
|
|
41
|
+
`data-button-width` takes `auto`, `standard`, or `full`.
|
|
42
|
+
|
|
43
|
+
**Use the button recipe only on elements that Helix does not render**, such as
|
|
44
|
+
an `<a>` styled as a button. For a button, use `helix-button`. The recipe has no
|
|
45
|
+
loading state, no pressed state, and no `type="submit"` handling.
|
|
37
46
|
|
|
38
47
|
## Links
|
|
39
48
|
|
|
@@ -50,8 +59,8 @@ handling.
|
|
|
50
59
|
```
|
|
51
60
|
|
|
52
61
|
`data-link-size` and `data-link-underline` are the modifiers. `quiet` is for
|
|
53
|
-
navigation, where
|
|
54
|
-
|
|
62
|
+
navigation, where an underline on every row would distract. If a link opens a
|
|
63
|
+
new tab or window, say so in the link text, so it does not surprise your users.
|
|
55
64
|
|
|
56
65
|
## Surfaces and layout
|
|
57
66
|
|
|
@@ -61,32 +70,30 @@ context says so on its own, rather than surprising the reader.
|
|
|
61
70
|
<div data-dock="bottom-end">…</div>
|
|
62
71
|
```
|
|
63
72
|
|
|
64
|
-
`data-dock` pins
|
|
65
|
-
|
|
66
|
-
ancestor instead of the window.
|
|
73
|
+
`data-dock` pins an element to a corner of the window. `data-dock-within` pins it
|
|
74
|
+
to a corner of the nearest positioned ancestor.
|
|
67
75
|
|
|
68
76
|
## Surface axes
|
|
69
77
|
|
|
70
|
-
Two of the [visual axes](./visual-axes) describe a surface
|
|
71
|
-
|
|
78
|
+
Two of the [visual axes](./visual-axes) describe a surface. Use these attributes
|
|
79
|
+
to apply them to a plain element:
|
|
72
80
|
|
|
73
81
|
```html
|
|
74
82
|
<section data-material="glass">…</section>
|
|
75
83
|
<div data-separation="elevated">…</div>
|
|
76
84
|
```
|
|
77
85
|
|
|
78
|
-
`data-material` takes `glass`, `frosted
|
|
79
|
-
takes `elevated`, `filled`, `outlined
|
|
80
|
-
so
|
|
81
|
-
that is `glass` and a component
|
|
82
|
-
|
|
83
|
-
material](./elevation-and-material).
|
|
86
|
+
`data-material` takes `glass`, `frosted`, and `transparent`. `data-separation`
|
|
87
|
+
takes `elevated`, `filled`, `outlined`, and `plain`. The values are the same as
|
|
88
|
+
the axes' values, so each word means the same thing here as on a component. A
|
|
89
|
+
`<section>` that is `glass` and a component with `material="glass"` get the same
|
|
90
|
+
treatment. See [Elevation and material](./elevation-and-material).
|
|
84
91
|
|
|
85
|
-
**Blur
|
|
86
|
-
`backdrop-filter
|
|
87
|
-
|
|
88
|
-
scroll pays
|
|
89
|
-
|
|
92
|
+
**Blur costs the most to render.** `glass` and `frosted` both use a
|
|
93
|
+
`backdrop-filter`. The compositor re-reads what is behind the element on every
|
|
94
|
+
frame in which the element moves. A full-width band that stays on screen while
|
|
95
|
+
you scroll pays that cost the whole time. To show depth, use `data-separation`,
|
|
96
|
+
which costs less.
|
|
90
97
|
|
|
91
98
|
## Prose
|
|
92
99
|
|
|
@@ -97,11 +104,16 @@ scroll pays continuously. Where the effect is about depth rather than texture,
|
|
|
97
104
|
</article>
|
|
98
105
|
```
|
|
99
106
|
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
In prose:
|
|
108
|
+
|
|
109
|
+
- Headings use the type scale.
|
|
110
|
+
- Paragraphs use the measure and leading.
|
|
111
|
+
- Lists, links, and inline code follow the same styles.
|
|
102
112
|
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
See [Typography](./typography).
|
|
114
|
+
|
|
115
|
+
If you control the Markdown renderer, map two elements to components, because
|
|
116
|
+
HTML alone cannot hold what they need:
|
|
105
117
|
|
|
106
118
|
- **Fenced code** to `helix-code-block`, with the fence's language as its `label`.
|
|
107
119
|
A `<pre>` has no label or copy button.
|
|
@@ -109,21 +121,21 @@ can't carry what they need:
|
|
|
109
121
|
tone. `NOTE` and `IMPORTANT` become `tone="info"`, `TIP` becomes `success`,
|
|
110
122
|
`WARNING` becomes `warning`, and `CAUTION` becomes `danger`.
|
|
111
123
|
|
|
112
|
-
Prose spaces each
|
|
124
|
+
Prose spaces each component the same as the element it replaces.
|
|
113
125
|
|
|
114
126
|
## Region axes
|
|
115
127
|
|
|
116
|
-
These two are API
|
|
117
|
-
|
|
128
|
+
These two attributes are API. Import the base layer for them, even in an app
|
|
129
|
+
that uses only components:
|
|
118
130
|
|
|
119
131
|
```html
|
|
120
132
|
<div data-density="sm">…</div>
|
|
121
133
|
<div data-color-mode="dark">…</div>
|
|
122
134
|
```
|
|
123
135
|
|
|
124
|
-
`data-density` sets
|
|
125
|
-
custom properties so it crosses every shadow boundary
|
|
126
|
-
|
|
136
|
+
`data-density` sets the size of the controls in a region. It works through
|
|
137
|
+
custom properties, so it crosses every shadow boundary. `data-color-mode` sets
|
|
138
|
+
the color mode for a subtree. See [Size and
|
|
127
139
|
density](./size-and-density) and [Color modes](./color-modes).
|
|
128
140
|
|
|
129
141
|
## Utilities
|
|
@@ -132,11 +144,16 @@ density](./size-and-density) and [Color modes](./color-modes).
|
|
|
132
144
|
<span data-hidden-visually>Sorting by</span>
|
|
133
145
|
```
|
|
134
146
|
|
|
135
|
-
|
|
136
|
-
[Accessibility](./accessibility).
|
|
147
|
+
`data-hidden-visually` clips the element, so it stays in the accessibility tree.
|
|
148
|
+
`display: none` would remove it. See [Accessibility](./accessibility).
|
|
149
|
+
|
|
150
|
+
## When to use a component
|
|
151
|
+
|
|
152
|
+
A recipe sets appearance and has no behavior. A recipe cannot:
|
|
137
153
|
|
|
138
|
-
|
|
154
|
+
- manage state
|
|
155
|
+
- take part in a form
|
|
156
|
+
- trap focus
|
|
157
|
+
- handle the keyboard
|
|
139
158
|
|
|
140
|
-
|
|
141
|
-
participate in a form, cannot trap focus and has no keyboard handling. If you
|
|
142
|
-
find yourself adding script to a recipe, the component is what you wanted.
|
|
159
|
+
If you need to add a script to a recipe, use the component.
|