@fusion.dev/helix-docs 0.104.1 → 0.106.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.
Files changed (48) hide show
  1. package/content/accessibility.mdx +92 -71
  2. package/content/angular.mdx +26 -24
  3. package/content/browser-support.mdx +61 -58
  4. package/content/building-on-the-headless-tier.mdx +100 -74
  5. package/content/charting.mdx +98 -79
  6. package/content/coding-agents.mdx +87 -69
  7. package/content/color-modes.mdx +40 -37
  8. package/content/color.mdx +67 -54
  9. package/content/composition.mdx +85 -83
  10. package/content/elevation-and-material.mdx +32 -29
  11. package/content/events.mdx +77 -65
  12. package/content/forms.mdx +69 -58
  13. package/content/iconography.mdx +75 -71
  14. package/content/installation.mdx +77 -68
  15. package/content/intent-reference.mdx +59 -54
  16. package/content/introduction.mdx +25 -23
  17. package/content/localization.mdx +122 -82
  18. package/content/maps.mdx +431 -0
  19. package/content/metrics.mdx +296 -299
  20. package/content/motion.mdx +44 -36
  21. package/content/other-frameworks.mdx +33 -31
  22. package/content/overlays.mdx +72 -54
  23. package/content/overriding-a-component.mdx +85 -74
  24. package/content/react.mdx +72 -64
  25. package/content/recipes.mdx +64 -47
  26. package/content/routing.mdx +100 -93
  27. package/content/sandbox.mdx +39 -39
  28. package/content/server-rendering.mdx +95 -84
  29. package/content/shape-and-borders.mdx +44 -37
  30. package/content/size-and-density.mdx +51 -46
  31. package/content/space-and-size.mdx +41 -34
  32. package/content/state-and-control.mdx +63 -51
  33. package/content/surfaces-and-separation.mdx +55 -53
  34. package/content/svelte.mdx +20 -19
  35. package/content/theme-builder.mdx +42 -31
  36. package/content/theming.mdx +58 -51
  37. package/content/tiers.mdx +69 -61
  38. package/content/tokens.mdx +72 -53
  39. package/content/typography.mdx +47 -47
  40. package/content/using-helix-with-an-agent.mdx +147 -115
  41. package/content/using-the-elements.mdx +55 -50
  42. package/content/versioning.mdx +42 -35
  43. package/content/visual-axes.mdx +168 -146
  44. package/content/vue.mdx +24 -24
  45. package/content/without-a-bundler.mdx +40 -23
  46. package/dist/pages.generated.js +49 -43
  47. package/dist/sources.generated.js +3548 -2682
  48. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Binding events, registering elements, and the traps in both.
2
+ description: Bind events, register the elements, and import the styles in a React app.
3
3
  pinned: true
4
4
  section: Essentials
5
5
  title: Using the elements
@@ -7,8 +7,8 @@ title: Using the elements
7
7
 
8
8
  # Using the elements
9
9
 
10
- Write `<helix-card>` in your JSX. They are plain custom elements: no wrapper, no
11
- patched React, and no React package: there is not one.
10
+ Write `<helix-card>` in your JSX. The elements are plain custom elements. There
11
+ is no wrapper component, no patched React, and no React package.
12
12
 
13
13
  ```tsx
14
14
  export default function Page() {
@@ -21,8 +21,7 @@ export default function Page() {
21
21
  }
22
22
  ```
23
23
 
24
- Everything below is a trap that has actually cost time, rather than general
25
- advice.
24
+ Each section below covers a problem that has cost us time in practice.
26
25
 
27
26
  ## Bind Helix events with `onhelix-*`
28
27
 
@@ -30,46 +29,48 @@ advice.
30
29
  <helix-tabs onhelix-before-activate={(event) => setPane(event.detail.value)} />
31
30
  ```
32
31
 
33
- There is a real bug underneath this, and the elements work around it for you.
34
- **React attaches no custom element listener while hydrating**, so on a
35
- server-rendered page every one of these props is dead until React commits an
36
- update for some other reason, at which point it silently starts working. Nothing
37
- is logged. It is
38
- [facebook/react#35446](https://github.com/facebook/react/issues/35446), open and
39
- unfixed.
32
+ React attaches no custom element listeners while it hydrates. On a
33
+ server-rendered page, these props do nothing until React commits an update for
34
+ some other reason. Then they start working, and nothing is logged either way.
35
+ The bug is [facebook/react#35446](https://github.com/facebook/react/issues/35446),
36
+ and it is still open. The elements work around it for you.
40
37
 
41
- Every Helix element binds the handler itself, immediately before it announces
42
- anything, using the function React is already holding for it. Measured in Chrome
43
- against React 19.2.8: on a hydrated page the first event reaches the handler,
44
- and it is never delivered twice once React binds its own listener.
38
+ Every Helix element binds the handler itself, just before it dispatches any
39
+ event, using the function React already holds for it. We measured this in
40
+ Chrome against React 19.2.8. On a hydrated page, the first event reaches the
41
+ handler. After React binds its own listener, no event is delivered twice.
45
42
 
46
- Nothing is required of you, and nothing changes once React fixes it.
43
+ You do not need to do anything, and nothing changes when React fixes the bug.
47
44
 
48
- React's own events are unaffected where they bubble. `onClick` on a
49
- `<helix-button>` goes through the synthetic system, which hydration does set up.
45
+ React's own events work when they bubble. `onClick` on a `<helix-button>` goes
46
+ through React's synthetic event system, which hydration sets up.
50
47
 
51
- A few of ours are native events relayed from inside the component, and the ones
52
- that do not bubble (`load` and `error` on Avatar, `ended`, `play` and `pause` on
53
- Video) reach nothing React sets up. The elements bind those for you, so
54
- `onError` on a `<helix-avatar>` works like the rest.
48
+ A few Helix events are native events relayed from inside the component. The ones
49
+ that do not bubble never reach React's listeners:
55
50
 
56
- ## The prop is `on` plus the event name
51
+ - `load` and `error` on Avatar
52
+ - `ended`, `play`, and `pause` on Video
57
53
 
58
- React slices `on` off the prop and listens for exactly what is left, without
59
- inspecting it.
54
+ The elements bind these for you, so `onError` on a `<helix-avatar>` works like
55
+ any other handler.
56
+
57
+ ## Write the prop as `on` plus the event name
58
+
59
+ React removes `on` from the prop name and listens for exactly the rest, as
60
+ written.
60
61
 
61
62
  - `onhelix-before-open` reaches `helix-before-open`. ✅
62
63
  - `onhelix-sample-start` reaches `helix-sample-start`. ✅
63
- - `onHelixOpen` binds an event called `HelixOpen`, which nobody dispatches. ❌
64
+ - `onHelixOpen` binds an event called `HelixOpen`, which is never dispatched. ❌
64
65
 
65
- The number of hyphens does not matter, measured in Chrome against React 19.2.8.
66
+ The number of hyphens does not matter. We measured this in Chrome against React
67
+ 19.2.8.
66
68
 
67
- ## Register once, in a client component
69
+ ## Register the elements in one client component
68
70
 
69
- A custom element registers as a side effect of importing its module, and that
70
- import has to be in the client graph to ever run. A server component's imports
71
- do not ship to the browser. So one client component holds every element import
72
- and renders `null`:
71
+ A custom element registers when you import its module. That import runs only if
72
+ it is in the client graph, and a server component's imports do not ship to the
73
+ browser. Put every element import in one client component that renders `null`:
73
74
 
74
75
  ```tsx
75
76
  'use client'
@@ -82,9 +83,9 @@ export function HelixElements(): null {
82
83
  ```
83
84
 
84
85
  Render it once in your layout. **Your pages stay server components.** An
85
- unregistered tag is just an unknown element in the HTML that upgrades when the
86
- definition lands. Asking you to mark every page `'use client'` to use a button
87
- would not be a design system.
86
+ unregistered tag is an unknown element in the HTML, and it upgrades when the
87
+ definition loads. You do not need to mark any page `'use client'` to use a
88
+ button.
88
89
 
89
90
  ## Import `elements.css` beside the base layer
90
91
 
@@ -93,13 +94,13 @@ import '@fusion.dev/helix-styles/base.css'
93
94
  import '@fusion.dev/helix-styles/helix.css'
94
95
  ```
95
96
 
96
- It hides each tag with `:not(:defined)` until it upgrades, using `visibility` so
97
- the page does not reflow. Without it a card arrives as a run of unstyled text
98
- and then snaps into a card.
97
+ `elements.css` hides each tag with `:not(:defined)` until the element upgrades.
98
+ It uses `visibility`, so the page does not reflow. Without it, a card appears as
99
+ unstyled text and then jumps into its card layout.
99
100
 
100
- It is generated from the element sources and enumerates the tags, because CSS
101
- cannot select "any custom element" and a bare `:not(:defined)` would also catch
102
- your framework's dev overlay.
101
+ We generate the file from the element sources, and it lists every tag by name.
102
+ CSS has no selector for any custom element, and a bare `:not(:defined)` would
103
+ also hide your framework's development overlay.
103
104
 
104
105
  ## Import from subpaths
105
106
 
@@ -108,16 +109,20 @@ import '@fusion.dev/helix/card' // ✅ one family
108
109
  import '@fusion.dev/helix' // ❌ the barrel
109
110
  ```
110
111
 
111
- One family per module, so you are not shipping the library to use a button.
112
+ Import one component family per module, so you do not ship the whole library to
113
+ use a button.
112
114
 
113
115
  ## Declarative shadow DOM is opt-in
114
116
 
115
- The site ships no DSD, and the shadow styles arrive with the definition rather
116
- than in the markup. You don't need to configure anything for that. If you render
117
- with Lit SSR yourself, its declarative shadow DOM hydrates: see
117
+ The site ships no declarative shadow DOM (DSD). The shadow styles load with the
118
+ element definition. You do not need to configure anything. If you render with
119
+ Lit SSR yourself, its declarative shadow DOM hydrates. See
118
120
  [Server rendering](./server-rendering).
119
121
 
120
- The short version of why: DSD cannot activate for script-inserted nodes, a
121
- server component's output is replayed from the flight payload through DOM APIs
122
- rather than re-run, and the patch that made it work hooked webpack, which
123
- Turbopack ignores, silently.
122
+ The site ships no DSD for three reasons:
123
+
124
+ - DSD cannot activate for nodes inserted by script.
125
+ - React inserts a server component's output by replaying the flight payload
126
+ through DOM APIs, without running the component again.
127
+ - The patch that made DSD work hooked into webpack, and Turbopack ignores that
128
+ hook without an error.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: What a version number means here, and which packages move together.
2
+ description: What a Helix version number means, and which packages are released together.
3
3
  order: 6
4
4
  section: Getting started
5
5
  title: Versioning
@@ -8,65 +8,72 @@ title: Versioning
8
8
  # Versioning
9
9
 
10
10
  **Every Helix package shares one version.** `@fusion.dev/helix@1.4.0` works with
11
- `@fusion.dev/helix-headless@1.4.0` and with `@fusion.dev/helix-styles@1.4.0`, and that is a
12
- guarantee rather than a coincidence: they are released together, always, from
13
- one tag.
11
+ `@fusion.dev/helix-headless@1.4.0` and with `@fusion.dev/helix-styles@1.4.0`.
12
+ This is guaranteed, because we always release them together, from one tag.
14
13
 
15
14
  ```sh
16
15
  bun add @fusion.dev/helix@1.4.0 @fusion.dev/helix-styles@1.4.0
17
16
  ```
18
17
 
19
- Pin them to the same number or pin none of them. A range that lets one drift
20
- ahead of another is the one configuration this scheme does not defend against.
18
+ Pin every Helix package to the same version, or pin none of them. The one setup
19
+ this versioning does not protect you from is a range that lets one package move
20
+ ahead of another.
21
21
 
22
- ## Why lockstep
22
+ ## Why Helix packages share one version
23
23
 
24
- Cortex moves independently. Full-repo lockstep would be wrong here because the
25
- documentation packages carry the version of what they document: publishing a
26
- Cortex fix would bump `@fusion.dev/helix-docs` to a version in which nothing about Helix
27
- changed.
24
+ Cortex has its own version. We did not give every package in the repository one
25
+ version, because the documentation packages carry the version of what they
26
+ document. With one version for everything, a Cortex fix would publish a new
27
+ version of `@fusion.dev/helix-docs` in which nothing about Helix changed.
28
28
 
29
- Per-domain lockstep keeps the property that matters, which is that two Helix
30
- packages of the same version are the pair that was tested together.
29
+ One version for Helix keeps the property that matters. Two Helix packages with
30
+ the same version were tested together.
31
31
 
32
- ## The version lives in the tag
32
+ ## The version number comes from the Git tag
33
33
 
34
- Every manifest in the repository holds `0.0.0-dev`. The real number is stamped
35
- in CI, seconds before packing.
34
+ Every manifest in the repository has the version `0.0.0-dev`. CI writes the real
35
+ number into each manifest seconds before packing.
36
36
 
37
- If you read the source: a manifest saying `0.0.0-dev` is not an unreleased
38
- package, it is every package. Committing the number back
39
- would need a bot whose push access outranks branch protection, to record
40
- something `git tag` already holds.
37
+ If you read the source, you will see `0.0.0-dev` on every package, including
38
+ released ones. We do not commit the real number back. That would need a bot
39
+ with push access that overrides branch protection, and `git tag` already records
40
+ the number.
41
41
 
42
- Two tag shapes, and the second is the useful one:
42
+ Releases use two kinds of tag:
43
43
 
44
44
  | Tag | Means |
45
45
  |---|---|
46
46
  | `helix-v1.4.0` | A release that promoted |
47
47
  | `helix-attempt-v1.4.0` | A number that was spent and did not ship |
48
48
 
49
- Version computation reads both, so a failed release burns a number rather than
50
- poisoning the next one. If you see 1.4.0 skipped, that is what happened.
49
+ The next version is computed from both kinds of tag. A failed release uses up
50
+ its number, and the next release gets a new one. If you see that 1.4.0 was
51
+ skipped, a release with that number failed.
51
52
 
52
53
  ## Documentation is versioned with the code
53
54
 
54
- `@fusion.dev/helix-docs@1.4.0` documents Helix 1.4.0. There is no version axis inside
55
- the package and no version switcher in it: the package version *is* the version,
56
- because every package in the domain moves together.
55
+ `@fusion.dev/helix-docs@1.4.0` documents Helix 1.4.0. The package documents one
56
+ version and has no version switcher. Its version number is the Helix version it
57
+ documents, because every Helix package shares one version.
57
58
 
58
- A site serving several versions installs several versions, which is the
59
- mechanism npm already provides and the only one that cannot drift.
59
+ To serve documentation for several versions, install several versions of the
60
+ package. npm already supports this, and it is the only approach that cannot fall
61
+ out of step with the code.
60
62
 
61
63
  ## Stability
62
64
 
63
- Components carry a `status` in the manifest and on their page: `experimental`,
64
- `stable`, or `deprecated`. Most of the library is experimental today and says
65
- so. That label is the honest one and it will not be softened to make the set
66
- look more finished than it is.
65
+ Each component has a `status` in the manifest and on its page. The status is
66
+ one of:
67
+
68
+ - `experimental`
69
+ - `stable`
70
+ - `deprecated`
71
+
72
+ Most components are experimental today, and their status says so. We will not
73
+ change a status to make the library look more finished than it is.
67
74
 
68
75
  ## Release notes
69
76
 
70
- On GitHub, generated from the tags. There is no changelog file in this package,
71
- because a second copy of the release notes is a second thing to keep in step and
72
- the one that goes stale is the one nobody is reading that week.
77
+ Release notes are on GitHub, generated from the tags. Helix has no changelog
78
+ file. A second copy of the release notes would have to be kept in step
79
+ with the first, and the copy nobody reads that week is the one that goes stale.