@fusion.dev/helix-docs 0.104.1 → 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,49 +1,62 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: What
|
|
2
|
+
description: What Helix components handle for you, what you handle, and what we do not test.
|
|
3
3
|
section: Foundations
|
|
4
4
|
title: Accessibility
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Accessibility
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
parts.
|
|
9
|
+
Helix components handle the structural parts of accessibility, such as roles,
|
|
10
|
+
keys, and focus. You handle the parts that depend on your content, such as
|
|
11
|
+
names, heading order, and language. A page built from accessible components is
|
|
12
|
+
accessible only when you also handle your parts.
|
|
13
13
|
|
|
14
|
-
## What the
|
|
14
|
+
## What the components handle
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
pattern its role implies: arrow keys move within a `Tabs`, a `Listbox` and a
|
|
18
|
-
`Menu`, `Escape` dismisses an overlay, `Home` and `End` go to the ends, typing
|
|
19
|
-
jumps to a match. None of that is yours to write.
|
|
16
|
+
### Roles, states, and keyboard interaction
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`Popover`.
|
|
18
|
+
Every component implements the keyboard pattern for its role. You do not write
|
|
19
|
+
any of it:
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
- Arrow keys move within `Tabs`, `Listbox`, and `Menu`.
|
|
22
|
+
- `Escape` closes an overlay.
|
|
23
|
+
- `Home` and `End` go to the first and last item.
|
|
24
|
+
- Typing jumps to a matching item.
|
|
25
|
+
|
|
26
|
+
### Focus
|
|
27
|
+
|
|
28
|
+
A `Dialog` traps focus while it is open and returns focus to the element that
|
|
29
|
+
opened it. `Drawer` and the modal mode of `Popover` do the same.
|
|
30
|
+
|
|
31
|
+
### Contrast
|
|
32
|
+
|
|
33
|
+
The theme engine measures each foreground color against the background it is
|
|
34
|
+
actually drawn on. It solves for the contrast target when it computes your
|
|
35
|
+
colors. Every pairing is then measured again on a laid-out page. That check
|
|
36
|
+
includes the many rules that set only a text color or only a background, so a
|
|
37
|
+
pairing nobody planned is still checked. See [Surfaces and
|
|
30
38
|
separation](./surfaces-and-separation).
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
### Reduced motion
|
|
41
|
+
|
|
42
|
+
Fifty-nine stylesheets respond to `prefers-reduced-motion` individually. Each
|
|
43
|
+
component needs its own rule because the base layer's global rule is
|
|
44
|
+
`*, *::before, *::after` in the document, and `*` does not cross a shadow
|
|
45
|
+
boundary. That rule reaches your prose and none of the components. The build
|
|
46
|
+
fails when a component animates without responding to `prefers-reduced-motion`.
|
|
47
|
+
|
|
48
|
+
### Disabled controls
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
`disabled` is mirrored to `aria-disabled`, and the control stays in the
|
|
51
|
+
accessibility tree. A screen reader can still announce that the control exists
|
|
52
|
+
and is turned off.
|
|
41
53
|
|
|
42
|
-
## What you
|
|
54
|
+
## What you handle
|
|
43
55
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
### Names
|
|
57
|
+
|
|
58
|
+
Every control takes `label`. A component renders the label you give it, and the
|
|
59
|
+
words are yours to choose. An icon-only control has no other text to name it:
|
|
47
60
|
|
|
48
61
|
```html
|
|
49
62
|
<helix-icon-button
|
|
@@ -52,66 +65,74 @@ go on:
|
|
|
52
65
|
></helix-icon-button>
|
|
53
66
|
```
|
|
54
67
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
`
|
|
58
|
-
|
|
68
|
+
### `label` and `aria-label`
|
|
69
|
+
|
|
70
|
+
`label` renders visible text and names the control through that text.
|
|
71
|
+
`aria-label` names the control and shows nothing on screen. Use `aria-label`
|
|
72
|
+
only when the page already makes the control's purpose plain. That case is less
|
|
73
|
+
common than it seems.
|
|
74
|
+
|
|
75
|
+
### Heading order
|
|
59
76
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
cannot know what is above it.
|
|
77
|
+
Components render the heading levels you give them. A `Card` does not add an
|
|
78
|
+
`h2` for you, because the right level depends on the headings above the card.
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
logical properties throughout, so a right-to-left document lays out correctly,
|
|
66
|
-
but nothing infers the direction for you.
|
|
67
|
-
See [Localization and RTL](./localization).
|
|
80
|
+
### Language and direction
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
Set `lang` and `dir` on the document. Components use logical properties
|
|
83
|
+
throughout, so a right-to-left document lays out correctly. Helix does not
|
|
84
|
+
detect the direction for you. See [Localization and RTL](./localization).
|
|
85
|
+
|
|
86
|
+
### Live regions for your own updates
|
|
87
|
+
|
|
88
|
+
Components announce their own state changes. To announce a message from your
|
|
89
|
+
application, put it in an `Announcement`:
|
|
71
90
|
|
|
72
91
|
```html
|
|
73
92
|
<helix-announcement tone="warning">Your trial ends on Friday.</helix-announcement>
|
|
74
93
|
```
|
|
75
94
|
|
|
76
|
-
`Announcement` is always a polite live region
|
|
77
|
-
interrupts whatever
|
|
78
|
-
|
|
79
|
-
announcement would
|
|
80
|
-
they had read anything.
|
|
95
|
+
`Announcement` is always a polite live region. An assertive region, such as
|
|
96
|
+
`role="alert"`, interrupts whatever the screen reader is reading. That suits a
|
|
97
|
+
message that appears during a session. It does not suit a message in the served
|
|
98
|
+
HTML, because an assertive announcement would interrupt a screen-reader user on
|
|
99
|
+
every page load, before they had read anything. A polite announcement can arrive
|
|
100
|
+
a moment later, and it is always safe to use.
|
|
81
101
|
|
|
82
|
-
|
|
83
|
-
|
|
102
|
+
`Callout` is a different component. It is a passage that interrupts a document
|
|
103
|
+
and is read where it sits. Neither component is a variant of the other.
|
|
84
104
|
|
|
85
105
|
## Two things the shadow boundary changes
|
|
86
106
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
107
|
+
`aria-labelledby` and `aria-describedby` inside a shadow root cannot point to an
|
|
108
|
+
id in your document. The browser drops the reference silently and reports no
|
|
109
|
+
error. For this reason, every control renders its own label, and connecting two
|
|
110
|
+
components by id does not work. See [Forms and validation](./forms).
|
|
111
|
+
|
|
112
|
+
A `<label for>` in your markup cannot reach into a shadow root either, so it
|
|
113
|
+
does not name a Helix control. Use the control's own `label`.
|
|
92
114
|
|
|
93
|
-
|
|
94
|
-
|
|
115
|
+
When a relationship has to cross the boundary, the components use
|
|
116
|
+
`ElementInternals` and element-reference properties. They are the only mechanism
|
|
117
|
+
that works across the boundary. Use the same tools when your own components need
|
|
118
|
+
such a relationship.
|
|
95
119
|
|
|
96
|
-
|
|
97
|
-
`ElementInternals` and element-reference properties rather than ids, which is
|
|
98
|
-
the only mechanism that works. If you need the same for your own composition,
|
|
99
|
-
that is the tool.
|
|
120
|
+
## Hide text visually
|
|
100
121
|
|
|
101
|
-
|
|
122
|
+
To hide text on screen and keep it for screen readers, add
|
|
123
|
+
`data-hidden-visually`:
|
|
102
124
|
|
|
103
125
|
```html
|
|
104
126
|
<span data-hidden-visually>Sorting by</span>
|
|
105
127
|
```
|
|
106
128
|
|
|
107
|
-
The base layer's `[data-hidden-visually]` clips
|
|
108
|
-
`display: none`
|
|
109
|
-
|
|
110
|
-
text is for.
|
|
129
|
+
The base layer's `[data-hidden-visually]` rule clips the element.
|
|
130
|
+
`display: none` and `visibility: hidden` both remove the element from the
|
|
131
|
+
accessibility tree, so they hide the text from screen readers too.
|
|
111
132
|
|
|
112
|
-
## What
|
|
133
|
+
## What we do not test
|
|
113
134
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
135
|
+
We test Helix in Chromium with automated specs and pixel baselines. We do not
|
|
136
|
+
run it through a screen reader on every release. The component patterns follow
|
|
137
|
+
the ARIA authoring practices, and they have not been certified against them. If
|
|
138
|
+
you find a real failure, report it as a bug.
|
package/content/angular.mdx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The schema Angular needs
|
|
2
|
+
description: The schema Angular needs to compile Helix tags, and how to bind properties and events.
|
|
3
3
|
parent: installation
|
|
4
4
|
section: Getting started
|
|
5
5
|
title: Angular
|
|
@@ -7,9 +7,9 @@ title: Angular
|
|
|
7
7
|
|
|
8
8
|
# Angular
|
|
9
9
|
|
|
10
|
-
Angular
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
Angular does not compile a template that contains a tag it does not recognize.
|
|
11
|
+
To use Helix components, add `CUSTOM_ELEMENTS_SCHEMA` to the components that
|
|
12
|
+
render them.
|
|
13
13
|
|
|
14
14
|
```ts
|
|
15
15
|
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'
|
|
@@ -22,11 +22,12 @@ import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'
|
|
|
22
22
|
export class SaveButton {}
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
`CUSTOM_ELEMENTS_SCHEMA`
|
|
27
|
-
template it is on
|
|
25
|
+
If you can, declare the schema only on the components that use Helix.
|
|
26
|
+
`CUSTOM_ELEMENTS_SCHEMA` turns off unknown-element checking for the whole
|
|
27
|
+
template it is on. A narrow scope keeps that check, which catches your own
|
|
28
|
+
typos, in your other components.
|
|
28
29
|
|
|
29
|
-
##
|
|
30
|
+
## Bind properties and events
|
|
30
31
|
|
|
31
32
|
```html
|
|
32
33
|
<helix-input
|
|
@@ -35,26 +36,27 @@ template it is on, so scoping it keeps the check for your own typos.
|
|
|
35
36
|
/>
|
|
36
37
|
```
|
|
37
38
|
|
|
38
|
-
`[prop]` sets a property, which is
|
|
39
|
-
binds with `addEventListener`, so the event name
|
|
39
|
+
`[prop]` sets a property, which a value that is not a string needs. `(event)`
|
|
40
|
+
binds with `addEventListener`, so use the event's own name.
|
|
40
41
|
|
|
41
|
-
**Do not use `attr.` for a stateful property.** `[attr.value]="name"` writes
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
**Do not use `attr.` for a stateful property.** `[attr.value]="name"` writes the
|
|
43
|
+
attribute. The attribute seeds the control and is out of date as soon as someone
|
|
44
|
+
types in it. The property holds the current value.
|
|
44
45
|
|
|
45
46
|
## No typings ship for Angular
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
own codebase from it.
|
|
48
|
+
The package has no `angular.d.ts`. `CUSTOM_ELEMENTS_SCHEMA` turns off the
|
|
49
|
+
checking that typings would feed, so Angular would not enforce a generated file.
|
|
50
|
+
We publish the manifest as `@fusion.dev/helix/custom-elements.json`, so you can
|
|
51
|
+
generate your own files from it.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
As a result, a misspelled property fails without an error in Angular. In React,
|
|
54
|
+
Vue, and Svelte, the same mistake is a compile error. Check property names in
|
|
55
|
+
code review.
|
|
55
56
|
|
|
56
|
-
##
|
|
57
|
+
## Refuse a change
|
|
57
58
|
|
|
58
|
-
`value`, `open`, `checked
|
|
59
|
-
|
|
60
|
-
and call `preventDefault()`. See
|
|
59
|
+
`value`, `open`, `checked`, and `active` are seeds. The element starts with the
|
|
60
|
+
value you set and then applies its own changes. To refuse a change, listen for
|
|
61
|
+
the `helix-before-*` event and call `preventDefault()`. See
|
|
62
|
+
[State and control](./state-and-control).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The
|
|
2
|
+
description: The browser features Helix uses, and the browser we test in.
|
|
3
3
|
order: 5
|
|
4
4
|
section: Getting started
|
|
5
5
|
title: Browser support
|
|
@@ -7,21 +7,20 @@ title: Browser support
|
|
|
7
7
|
|
|
8
8
|
# Browser support
|
|
9
9
|
|
|
10
|
-
Helix
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
Helix uses browser features directly, with no compatibility layer. It has no
|
|
11
|
+
polyfills, no transpiled fallback, and no setting that trades features for
|
|
12
|
+
support in older browsers. Your browser needs every feature Helix uses.
|
|
13
13
|
|
|
14
|
-
## What
|
|
14
|
+
## What we test
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
We test in Chromium, through Playwright. The DOM specs run in it, and 83 pixel
|
|
17
17
|
baselines are captured in it, on Linux, with the network blocked.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
report we want, and it is not one we would have caught.
|
|
19
|
+
We do not run the tests in Firefox or Safari. The rest of this page lists the
|
|
20
|
+
browser features Helix uses. If you ship Helix to Firefox or Safari and find
|
|
21
|
+
something broken, please report it. Our tests would not have caught it.
|
|
23
22
|
|
|
24
|
-
##
|
|
23
|
+
## Browser features Helix uses
|
|
25
24
|
|
|
26
25
|
| Feature | Where |
|
|
27
26
|
|---|---|
|
|
@@ -35,55 +34,59 @@ report we want, and it is not one we would have caught.
|
|
|
35
34
|
| `:state()` | Every boolean state the library publishes: `open`, `checked`, `selected`, `invalid`, `read`, `has-label`, `settled`, `empty`, `controls` |
|
|
36
35
|
| `CSS.highlights` | Filter-match highlighting, in `Command` and `Combobox` |
|
|
37
36
|
|
|
38
|
-
Positioning
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
37
|
+
Positioning uses `@floating-ui/dom`. We chose this on purpose, and it is the one
|
|
38
|
+
place Helix takes a dependency for something the browser could do. CSS anchor
|
|
39
|
+
positioning is not yet available in every browser that has the rest of these
|
|
40
|
+
features.
|
|
41
|
+
|
|
42
|
+
## Which features set the minimum browser
|
|
43
|
+
|
|
44
|
+
**Check for `light-dark()` and the Popover API.** They are the newest features
|
|
45
|
+
Helix requires, and everything else in the table has been available longer.
|
|
46
|
+
Helix depends on both. Every token uses `light-dark()` to set both color modes
|
|
47
|
+
in one declaration. Every overlay uses the Popover API to draw in the top layer.
|
|
48
|
+
|
|
49
|
+
Neither one has a useful fallback:
|
|
50
|
+
|
|
51
|
+
- A browser without `light-dark()` shows no color at all.
|
|
52
|
+
- A browser without the Popover API renders overlays in the page flow.
|
|
53
|
+
|
|
54
|
+
For that reason, this page has no support table with a fallback column. Helix
|
|
55
|
+
has no partial mode.
|
|
56
|
+
|
|
57
|
+
Chromium 132 has both features. We measured on September 15, 2026 that it
|
|
58
|
+
does not support two things your stylesheet can do through `::part()`:
|
|
59
|
+
|
|
60
|
+
- It ignores a range input's `::-webkit-slider-thumb` and
|
|
61
|
+
`::-webkit-slider-runnable-track` after a part.
|
|
62
|
+
- It looks for the `@keyframes` that a `::part()` rule names inside the
|
|
63
|
+
component's shadow root, so no animation starts.
|
|
64
|
+
|
|
65
|
+
The headless examples use neither.
|
|
66
|
+
|
|
67
|
+
`:state()` is the third newest feature. It does not set the minimum browser,
|
|
68
|
+
because components still work without it. A component that cannot record a
|
|
69
|
+
state keeps the look of its resting rule, so a checkbox is drawn unchecked.
|
|
70
|
+
Helix tests for `:state()` support in the one place that records states.
|
|
71
|
+
|
|
72
|
+
## Browsers without `CSS.highlights`
|
|
73
|
+
|
|
74
|
+
`Command` and `Combobox` use the CSS Custom Highlight API to highlight the
|
|
75
|
+
matched text in their filtered results. It is the least widely available
|
|
76
|
+
feature Helix uses, and it is the only one that degrades gracefully. Without it,
|
|
77
|
+
the results still filter, sort, and select correctly, and the match is not
|
|
74
78
|
highlighted.
|
|
75
79
|
|
|
76
|
-
Nothing else in
|
|
80
|
+
Nothing else in Helix uses it.
|
|
77
81
|
|
|
78
|
-
##
|
|
82
|
+
## Older browsers
|
|
79
83
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
Helix does not support Internet Explorer and uses no polyfills. It has no
|
|
85
|
+
`browserslist`, no transpilation target, and no build flag for older browsers.
|
|
86
|
+
We decided this on purpose. Components that are custom elements cannot run in a
|
|
87
|
+
browser without custom elements, and every other feature in the table arrived in
|
|
88
|
+
the same generation of browsers.
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
See [Without a bundler](./without-a-bundler).
|
|
90
|
+
To support an older browser, use the base layer. `@fusion.dev/helix-styles` is
|
|
91
|
+
plain CSS with no JavaScript. Markup built from its recipes works in much older
|
|
92
|
+
browsers than the components do. See [Without a bundler](./without-a-bundler).
|