@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
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Build your own design system on the Helix headless tier, with your own tag names and styles.
|
|
3
3
|
section: Essentials
|
|
4
4
|
title: Building on the headless tier
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Building on the headless tier
|
|
8
8
|
|
|
9
|
-
The headless tier is a set of components with no stylesheet
|
|
10
|
-
|
|
11
|
-
looks. That makes it usable as a foundation rather than as a library you consume
|
|
12
|
-
whole. Your tags, your stylesheets, our accessibility.
|
|
9
|
+
The headless tier is a set of components with no stylesheet. Each component
|
|
10
|
+
provides:
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
- structure
|
|
13
|
+
- ARIA
|
|
14
|
+
- keyboard behavior
|
|
15
|
+
- state
|
|
16
|
+
- form participation
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
None of it sets how the component looks. You can use the headless tier as the
|
|
19
|
+
foundation of your own design system, with your own tag names and your own
|
|
20
|
+
stylesheets.
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
Theming Helix keeps our components and changes their tokens. Building on the
|
|
23
|
+
headless tier keeps our behavior and replaces the whole presentation layer,
|
|
24
|
+
under names of your own.
|
|
25
|
+
|
|
26
|
+
## Set your own tag prefix
|
|
27
|
+
|
|
28
|
+
Every headless component renders its children with an interpolated tag name.
|
|
29
|
+
The prefix of that name comes from a static on the class:
|
|
22
30
|
|
|
23
31
|
```ts
|
|
24
32
|
import { HelixHeadlessCombobox } from '@fusion.dev/helix-headless/combobox'
|
|
@@ -30,19 +38,18 @@ export class AcmeCombobox extends HelixHeadlessCombobox {
|
|
|
30
38
|
customElements.define('acme-combobox', AcmeCombobox)
|
|
31
39
|
```
|
|
32
40
|
|
|
33
|
-
That
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
That one line sets the prefix. The styled tier sets its prefix the same way, with
|
|
42
|
+
`static override tier = 'helix-'` and nothing else. The static appears 116 times
|
|
43
|
+
in the headless manifest, so you can find it there.
|
|
36
44
|
|
|
37
|
-
##
|
|
45
|
+
## Register every component a component renders
|
|
38
46
|
|
|
39
|
-
**
|
|
40
|
-
one of them is obvious.**
|
|
47
|
+
**When a component renders another component, register both.**
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
If you register `acme-combobox` without `acme-listbox`, the panel renders a tag
|
|
50
|
+
that is not defined. The browser shows no error or warning. An unregistered
|
|
51
|
+
custom element is an inert, unstyled inline box, so the combobox appears not to
|
|
52
|
+
open.
|
|
46
53
|
|
|
47
54
|
[//]: # (renders)
|
|
48
55
|
|
|
@@ -71,22 +78,24 @@ a combobox that appears not to open.
|
|
|
71
78
|
|
|
72
79
|
[//]: # (/renders)
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
reaches `option`.
|
|
81
|
+
Subclass and register each family together with everything it renders, and
|
|
82
|
+
everything those families render in turn. For example, `command` reaches
|
|
83
|
+
`dialog` and `listbox`, and `listbox` reaches `option`.
|
|
84
|
+
|
|
85
|
+
We generate the table from the manifest, which publishes the graph as
|
|
86
|
+
`helix.renders` on every element that interpolates a tag. We kept the table by
|
|
87
|
+
hand until September 22, 2026. By then, four families in it were wrong. The
|
|
88
|
+
generated table is always current.
|
|
77
89
|
|
|
78
|
-
|
|
79
|
-
`helix.renders` on every element that interpolates a tag. It was kept by hand
|
|
80
|
-
until 22 September 2026 and was wrong by four families when it stopped being, so
|
|
81
|
-
read it as current rather than as maintained.
|
|
90
|
+
## What you write yourself
|
|
82
91
|
|
|
83
|
-
|
|
92
|
+
### A `:not(:defined)` rule
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
`@fusion.dev/helix` ships an `elements.css` that hides each of its tags until
|
|
95
|
+
the tag's definition loads. Your page then does not show unstyled text that
|
|
96
|
+
changes into components. The headless package ships no such file, and no tool
|
|
97
|
+
can generate one for tags you have not named yet. Write the rule for your own
|
|
98
|
+
elements:
|
|
90
99
|
|
|
91
100
|
```css
|
|
92
101
|
acme-combobox:not(:defined),
|
|
@@ -95,12 +104,13 @@ acme-listbox:not(:defined) {
|
|
|
95
104
|
}
|
|
96
105
|
```
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
definitions arrive.
|
|
107
|
+
Use `visibility` so the page does not reflow when the definitions arrive.
|
|
100
108
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
### Typings for your tags
|
|
110
|
+
|
|
111
|
+
`@fusion.dev/helix-cem` is the generator we use for our own typings. It reads
|
|
112
|
+
your package and writes `jsx.d.ts`, `vue.d.ts`, and `svelte.d.ts` for your tags,
|
|
113
|
+
with every member your subclasses inherit from ours. Add a `cem.config.ts`
|
|
104
114
|
beside your `package.json`:
|
|
105
115
|
|
|
106
116
|
```ts
|
|
@@ -113,11 +123,13 @@ export default {
|
|
|
113
123
|
} satisfies HelixCemOptions
|
|
114
124
|
```
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
`dependencies
|
|
118
|
-
|
|
126
|
+
Then run `bun --bun helix-cem`. It finds the classes you extend through your
|
|
127
|
+
`dependencies`. The typings for `acme-combobox` then include the hundred or so
|
|
128
|
+
members it inherits, as well as the two you wrote.
|
|
129
|
+
|
|
130
|
+
### The tag map
|
|
119
131
|
|
|
120
|
-
|
|
132
|
+
Write the tag map yourself, with one line per element, beside the class:
|
|
121
133
|
|
|
122
134
|
```ts
|
|
123
135
|
declare global {
|
|
@@ -127,43 +139,57 @@ declare global {
|
|
|
127
139
|
}
|
|
128
140
|
```
|
|
129
141
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
TypeScript declares custom elements this way. The interface merges from your
|
|
143
|
+
source, and a generated file cannot name a class that is not in the same
|
|
144
|
+
program.
|
|
145
|
+
|
|
146
|
+
## What the headless tier handles for you
|
|
147
|
+
|
|
148
|
+
### Tree-shaking
|
|
149
|
+
|
|
150
|
+
`@fusion.dev/helix-headless` declares `sideEffects: ["./dist/**/*.js"]`. The
|
|
151
|
+
declaration is accurate, because the modules register elements when you import
|
|
152
|
+
them. A bundler that treated them as free of side effects would drop a
|
|
153
|
+
registration, and a tag would never upgrade.
|
|
154
|
+
|
|
155
|
+
### Documented parts
|
|
156
|
+
|
|
157
|
+
Every part has an `@csspart` entry, so every `::part()` you can use is
|
|
158
|
+
published. You write your presentation layer against these named parts, and it
|
|
159
|
+
does not depend on our internal markup.
|
|
160
|
+
|
|
161
|
+
### Behavior
|
|
162
|
+
|
|
163
|
+
These features live below the tier you replace, so they keep working under your
|
|
164
|
+
tag names:
|
|
133
165
|
|
|
134
|
-
|
|
166
|
+
- focus management
|
|
167
|
+
- typeahead
|
|
168
|
+
- the roving tab stop
|
|
169
|
+
- form participation
|
|
170
|
+
- validity
|
|
135
171
|
|
|
136
|
-
|
|
137
|
-
`sideEffects: ["./dist/**/*.js"]`, which is true rather than convenient: the
|
|
138
|
-
modules register elements on import, so a bundler that believed otherwise would
|
|
139
|
-
drop a registration and leave you debugging a tag that does not upgrade.
|
|
172
|
+
## `tier` is not yet a versioned API
|
|
140
173
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
174
|
+
`tier` is an implementation detail that is visible in the manifest. Using it to
|
|
175
|
+
set your own prefix makes it an API that needs a stability contract, and we
|
|
176
|
+
have not written that contract yet. The pattern is supported but not yet
|
|
177
|
+
versioned, so pin your Helix version.
|
|
145
178
|
|
|
146
|
-
|
|
147
|
-
form participation and validity all live below the tier you are replacing, so
|
|
148
|
-
they keep working under your names.
|
|
179
|
+
## Building on the headless tier compared with white-labeling
|
|
149
180
|
|
|
150
|
-
|
|
181
|
+
Building on the headless tier fits you if you are building a design system on
|
|
182
|
+
top of ours and our tags can appear beside yours.
|
|
151
183
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
attached, and that contract is not written. Treat this as a supported pattern
|
|
155
|
-
that is not yet a versioned promise, and pin your Helix version.
|
|
184
|
+
White-labeling fits a customer who wants Helix shipped under their own name,
|
|
185
|
+
with no Helix tags. It costs more, and it needs:
|
|
156
186
|
|
|
157
|
-
|
|
187
|
+
- the tag literals rewritten at build time
|
|
188
|
+
- a second distribution to publish
|
|
189
|
+
- an artifact per customer
|
|
158
190
|
|
|
159
|
-
|
|
160
|
-
one building a design system on top of ours and content for our tags to sit
|
|
161
|
-
beside theirs. The other wants Helix shipped under their name with ours absent,
|
|
162
|
-
which is a different and more expensive mechanism: rewriting the tag literals at
|
|
163
|
-
build time, a second distribution to publish, and an artifact per customer.
|
|
164
|
-
Nothing on this page needs any of that.
|
|
191
|
+
Building on the headless tier needs none of these.
|
|
165
192
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
it.
|
|
193
|
+
You own the presentation layer, the tags, and the build. If we stopped
|
|
194
|
+
tomorrow, you would keep a working design system. You would lose our fixes to
|
|
195
|
+
the behavior underneath it.
|
package/content/charting.mdx
CHANGED
|
@@ -1,37 +1,49 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Which chart to use, and how charts read their data from a table in the document.
|
|
3
3
|
section: Essentials
|
|
4
4
|
title: Charting
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Charting
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
`Scatter Chart`, `Donut Chart`, `Heatmap`, `Sparkline`, `Trend` and the shared
|
|
11
|
-
`Legend`. Each has its own API page. Here is which one answers which question,
|
|
12
|
-
and how the data gets in, which is the same for all of them.
|
|
9
|
+
Helix has these chart families, and each one has its own API page:
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
- `Bar Chart`
|
|
12
|
+
- `Line Chart`
|
|
13
|
+
- `Area Chart`
|
|
14
|
+
- `Scatter Chart`
|
|
15
|
+
- `Donut Chart`
|
|
16
|
+
- `Heatmap`
|
|
17
|
+
- `Sparkline`
|
|
18
|
+
- `Trend`
|
|
19
|
+
- `Legend`, which all of the charts share
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
This guide covers which chart fits which question, and how data gets into a
|
|
22
|
+
chart. Data gets in the same way for every chart.
|
|
23
|
+
|
|
24
|
+
## Choose a chart
|
|
25
|
+
|
|
26
|
+
Choose a chart by the question it answers.
|
|
17
27
|
|
|
18
28
|
- **How much, compared.** `Bar Chart`. A bar's length is its value, so it always
|
|
19
29
|
starts at zero.
|
|
20
30
|
- **How something moved over time.** `Line Chart`. It measures from the data's
|
|
21
31
|
own range, so a small change still shows. Its `area` puts a light wash under
|
|
22
|
-
each line
|
|
32
|
+
each line. Each wash is drawn from the floor on its own and overlaps the
|
|
33
|
+
others.
|
|
23
34
|
- **How a total is made up over time.** `Area Chart`. Each column is stacked on
|
|
24
35
|
the one below, so the top edge is the total and a band's thickness is its
|
|
25
|
-
share.
|
|
26
|
-
|
|
27
|
-
adds them.
|
|
36
|
+
share. Use it when the parts add up to a total. `Line Chart` with `area`
|
|
37
|
+
overlaps the series, and `Area Chart` adds them.
|
|
28
38
|
- **Parts of one whole, at one moment.** `Donut Chart`.
|
|
29
|
-
- **Whether two measures relate.** `Scatter Chart`, one point per row.
|
|
30
|
-
- **How each day or check went.** `Heatmap
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
- **Whether two measures relate.** `Scatter Chart`, with one point per row.
|
|
40
|
+
- **How each day or check went.** `Heatmap`, for uptime, contributions, or
|
|
41
|
+
activity.
|
|
42
|
+
- **The shape of a series beside its number.** `Sparkline`, drawn with no axes.
|
|
43
|
+
Use `Trend` to show which way one measurement moved and whether that is good
|
|
44
|
+
news.
|
|
33
45
|
|
|
34
|
-
##
|
|
46
|
+
## Charts read their data from a table
|
|
35
47
|
|
|
36
48
|
```html
|
|
37
49
|
<table id="revenue">
|
|
@@ -48,20 +60,19 @@ Pick by the question, not by the picture.
|
|
|
48
60
|
<helix-bar-chart for="revenue"></helix-bar-chart>
|
|
49
61
|
```
|
|
50
62
|
|
|
51
|
-
`for` points
|
|
52
|
-
|
|
53
|
-
convenience.
|
|
63
|
+
`for` points to a real `<table>` by id, and the chart reads its series from that
|
|
64
|
+
table. No other Helix component gets its data this way. There are two reasons.
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
markup, and a property is not markup
|
|
66
|
+
First, a property does not survive hydration. A framework's server render emits
|
|
67
|
+
markup, and a property is not markup. An array assigned to `items` exists only
|
|
57
68
|
after JavaScript has run, so the server has nothing to send and the first paint
|
|
58
|
-
has nothing to draw. Text in the document is the one channel that both
|
|
59
|
-
and
|
|
69
|
+
has nothing to draw. Text in the document is the one channel that both the
|
|
70
|
+
server and the client can see.
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
Second, the table is what a screen reader reads. A chart is a picture of
|
|
73
|
+
numbers, and a screen reader cannot read a picture. The table holds the numbers
|
|
74
|
+
in the document, where you can navigate them, and the chart draws them. If the
|
|
75
|
+
table should not be seen, hide it visually, and the data is still there:
|
|
65
76
|
|
|
66
77
|
```html
|
|
67
78
|
<table
|
|
@@ -70,67 +81,75 @@ Hide the table visually if it should not be seen, and the data is still there:
|
|
|
70
81
|
>…</table>
|
|
71
82
|
```
|
|
72
83
|
|
|
73
|
-
The caption becomes the chart's accessible name unless you set `label
|
|
74
|
-
usually the right words
|
|
84
|
+
The table's caption becomes the chart's accessible name unless you set `label`.
|
|
85
|
+
The caption usually has the right words already.
|
|
75
86
|
|
|
76
87
|
## Series colors
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
Helix has twenty-four series color tokens, in order, from
|
|
90
|
+
`--helix-color-series-1` to `--helix-color-series-24`. A chart with three series
|
|
91
|
+
uses the first three. The tokens are ordered so that each color
|
|
92
|
+
stays distinguishable from the ones before it. They are not designed to look
|
|
93
|
+
good as a full set of twenty-four.
|
|
81
94
|
|
|
82
|
-
The palette wraps
|
|
83
|
-
the legend beside it
|
|
95
|
+
The palette wraps after the last color. One number in one place sets where it
|
|
96
|
+
wraps, so a chart and the legend beside it always agree on each series' color.
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
Each mark in a chart carries its series color as a custom property. The chart
|
|
99
|
+
tracks which series each bar belongs to, and CSS cannot count that. With the
|
|
100
|
+
custom property, you can restyle a series from outside the chart without knowing
|
|
101
|
+
the drawing order.
|
|
88
102
|
|
|
89
|
-
##
|
|
103
|
+
## Add a legend
|
|
90
104
|
|
|
91
105
|
```html
|
|
92
106
|
<helix-legend for="revenue"></helix-legend>
|
|
93
107
|
<helix-bar-chart for="revenue"></helix-bar-chart>
|
|
94
108
|
```
|
|
95
109
|
|
|
96
|
-
The legend reads the same table, so
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
`
|
|
130
|
-
|
|
131
|
-
##
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
110
|
+
The legend reads the same table as the chart, so their names and colors always
|
|
111
|
+
match. They can differ only if you point them at two different tables.
|
|
112
|
+
|
|
113
|
+
## Charts on right-to-left pages
|
|
114
|
+
|
|
115
|
+
On a page with `dir="rtl"`, an axis that follows reading order starts on the
|
|
116
|
+
right, where the text starts. Categories and time follow reading order. The
|
|
117
|
+
words around a chart are HTML and change direction on their own. The drawing
|
|
118
|
+
changes direction with them, so the name under a column belongs to that column
|
|
119
|
+
in either direction. The pointer and the tooltip read the drawing the same way.
|
|
120
|
+
An axis of values keeps its own direction.
|
|
121
|
+
|
|
122
|
+
These parts change direction:
|
|
123
|
+
|
|
124
|
+
- `Bar Chart`'s columns, and its rows, which grow out of their names at the
|
|
125
|
+
right
|
|
126
|
+
- `Line Chart`, `Area Chart`, and `Sparkline`, with their end marks
|
|
127
|
+
- `Heatmap`'s weeks, which were already a grid laid out along the line
|
|
128
|
+
- A half `Donut Chart`, which is read across
|
|
129
|
+
|
|
130
|
+
These parts keep their direction:
|
|
131
|
+
|
|
132
|
+
- Values keep their vertical direction, because up means more in every script.
|
|
133
|
+
- Numerals are text beside the drawing, so none of them reads backwards.
|
|
134
|
+
- A whole `Donut Chart` keeps its first slice at twelve o'clock and runs
|
|
135
|
+
clockwise. That is a clock's convention, and it does not depend on the script.
|
|
136
|
+
- `Scatter Chart` is laid out as on a left-to-right page, with its y axis on the
|
|
137
|
+
left and larger values to the right. Both of its axes are measures, and a
|
|
138
|
+
number line runs that way in every script. Its axis names read in their own
|
|
139
|
+
direction, so a name in Arabic reads right to left under the far end of the
|
|
140
|
+
plot. Its summary and tooltip follow the page's direction.
|
|
141
|
+
|
|
142
|
+
To keep a chart left to right on a right-to-left page, such as a number line in
|
|
143
|
+
a mathematics text, set `dir="ltr"` on the chart element. You need nothing else.
|
|
144
|
+
|
|
145
|
+
## Chart animation and reduced motion
|
|
146
|
+
|
|
147
|
+
Charts animate when they appear and when their data changes. Every chart
|
|
148
|
+
responds to `prefers-reduced-motion`. See [Motion](./motion).
|
|
149
|
+
|
|
150
|
+
## What Helix charts do not include
|
|
151
|
+
|
|
152
|
+
Helix charts have no axis configuration language, no plugin system, and no chart
|
|
153
|
+
types that you build by composing scales. Each chart is a drawing that reads a
|
|
154
|
+
table and is styled by the token system, and the table is its accessible
|
|
155
|
+
representation. When you need a grammar of graphics, use a charting library.
|