@fusion.dev/helix-docs 0.0.0-dev → 0.0.3

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 (41) hide show
  1. package/content/browser-support.mdx +2 -2
  2. package/content/charting.mdx +4 -8
  3. package/content/coding-agents.mdx +14 -22
  4. package/content/color-modes.mdx +4 -4
  5. package/content/color.mdx +2 -2
  6. package/content/elevation-and-material.mdx +2 -2
  7. package/content/events.mdx +1 -1
  8. package/content/forms.mdx +5 -7
  9. package/content/iconography.mdx +15 -12
  10. package/content/installation.mdx +4 -6
  11. package/content/introduction.mdx +1 -1
  12. package/content/metrics.mdx +214 -214
  13. package/content/other-frameworks.mdx +6 -5
  14. package/content/overriding-a-component.mdx +11 -15
  15. package/content/routing.mdx +4 -4
  16. package/content/server-rendering.mdx +1 -1
  17. package/content/shape-and-borders.mdx +19 -8
  18. package/content/space-and-size.mdx +1 -1
  19. package/content/state-and-control.mdx +5 -5
  20. package/content/svelte.mdx +3 -3
  21. package/content/theme-builder.mdx +1 -1
  22. package/content/theming.mdx +1 -1
  23. package/content/tiers.mdx +2 -2
  24. package/content/tokens.mdx +4 -4
  25. package/content/using-helix-with-an-agent.mdx +30 -27
  26. package/content/using-the-elements.mdx +0 -2
  27. package/content/visual-axes.mdx +5 -7
  28. package/content/without-a-bundler.mdx +4 -5
  29. package/dist/catalog.d.ts +19 -29
  30. package/dist/catalog.js +27 -49
  31. package/dist/naming.js +1 -1
  32. package/dist/pages.generated.d.ts +1 -1
  33. package/dist/pages.generated.js +1 -1
  34. package/dist/reference.js +1 -1
  35. package/dist/registry.d.ts +3 -3
  36. package/dist/registry.js +3 -3
  37. package/dist/sections.d.ts +3 -7
  38. package/dist/sections.js +3 -7
  39. package/dist/sources.generated.d.ts +2 -2
  40. package/dist/sources.generated.js +367 -374
  41. package/package.json +6 -2
@@ -17,12 +17,14 @@ Three doors are open, and they are in the order you should try them.
17
17
 
18
18
  ```css
19
19
  :root {
20
- --helix-radii-md: 2px;
20
+ --helix-seed-radii: 2px;
21
21
  }
22
22
  ```
23
23
 
24
24
  If every card, dialog and button should be squarer, that is a token change and
25
- you are done. Tokens cross shadow boundaries on their own, because custom
25
+ you are done. The seed rather than `--helix-radii-md`, because the four rungs
26
+ are derived from it: `md` on its own is one step of four, and the buttons and
27
+ dialogs are on a different one. See [Shape and borders](./shape-and-borders). Tokens cross shadow boundaries on their own, because custom
26
28
  properties inherit, so one declaration reaches every component at once.
27
29
 
28
30
  Reach for this first. Most requests that arrive as "can I restyle the button"
@@ -51,10 +53,7 @@ changes that component and nothing else.
51
53
  after the component (`--card-padding`, `--drawer-radius`) and a token is named
52
54
  `--helix-*`. Every documented hook is held to a rule that actually reads it, in
53
55
  both directions: declared and never read is a promise with nothing behind it,
54
- and read and never declared is a working feature nobody is told about. Three of
55
- `Button`'s four hooks were inert for a refactor's worth of time while the
56
- reference went on listing them, which is how that check came
57
- to exist.
56
+ and read and never declared is a working feature nobody is told about.
58
57
 
59
58
  Each component's page lists its hooks under Custom properties.
60
59
 
@@ -77,10 +76,8 @@ internal structure.
77
76
 
78
77
  **A published part is a promise**, held both ways:
79
78
  a documented part that nothing renders, and a rendered part nobody was told
80
- about. The second is the worse of the two, because a `::part()` that resolves to
81
- nothing is valid CSS that matches nothing and reports nothing. `Breadcrumbs`
82
- published a `nav` part the family does not render; `Checkbox` renders the
83
- `field` part the whole styled appearance is built on and never declared it.
79
+ about. The first is the worse of the two for you, because a `::part()` that
80
+ resolves to nothing is valid CSS that matches nothing and reports nothing.
84
81
 
85
82
  Each component's page lists its parts.
86
83
 
@@ -105,12 +102,11 @@ its arrow is `tooltip-arrow`.
105
102
  `Command` forwarded the listbox's `search-field` under a name it also rendered
106
103
  itself, so `::part(search-field)` matched two elements at once.
107
104
 
108
- This is checked in both directions. `check:parts` holds a published part and a
109
- rendered one to each other, and `check:exportparts` holds a composition to
105
+ This is checked in both directions. `helix component`'s `parts` holds a published part and a
106
+ rendered one to each other, and `helix component`'s `exportparts` holds a composition to
110
107
  forwarding everything its child publishes, under one prefix, colliding with
111
- nothing. Before it existed, 148 published child parts were unreachable: all
112
- sixteen of the color picker's from inside a color input, all thirteen of the
113
- date picker's from inside a date input.
108
+ nothing. So every part the color picker publishes is reachable from inside a
109
+ color input, and every part the date picker publishes from inside a date input.
114
110
 
115
111
  If you still find a part you cannot reach, that is worth reporting rather than
116
112
  working around: the missing part is the bug.
@@ -34,9 +34,9 @@ amount of JavaScript reproduces:
34
34
  - right-click offers Copy Link Address
35
35
  - a crawler follows it
36
36
 
37
- Before `href` existed, the docs sidebar put a `<Link>` inside each row. The
38
- anchor was 57px of a 240px row, so five sixths of every row did nothing, and
39
- Enter did nothing at all: the tree announced a selection and no anchor heard it.
37
+ A `<Link>` inside each row buys none of it. In the docs sidebar the anchor was
38
+ 57px of a 240px row, so five sixths of every row did nothing, and Enter did
39
+ nothing at all: the tree announced a selection and no anchor heard it.
40
40
 
41
41
  ## `href` and a framework's `<Link>`
42
42
 
@@ -195,7 +195,7 @@ host is the only element the listbox can point at.
195
195
  same browser, the accessibility tree for `<div role="option"><a href>Open
196
196
  settings</a></div>` inside a listbox is an option with *no accessible name*, and
197
197
  the link exposed as a child of it. The sibling option with plain text is named
198
- correctly. So the manoeuvre that works for `treeitem` and `menuitem`, moving the
198
+ correctly. So the maneuver that works for `treeitem` and `menuitem`, moving the
199
199
  role onto the anchor, is exactly the one thing that cannot be done here.
200
200
 
201
201
  Two constraints pointing opposite ways, and no arrangement satisfies both.
@@ -39,7 +39,7 @@ has a tree.
39
39
  **Anything that inspects the tree runs in `firstUpdated` or later**, and is
40
40
  therefore a client-side enhancement by definition.
41
41
 
42
- ## Never initialise state in `connectedCallback`
42
+ ## Never initialize state in `connectedCallback`
43
43
 
44
44
  SSR does not call it. Derive from properties, or seed in `willUpdate`, which SSR
45
45
  does call.
@@ -25,18 +25,30 @@ square: a percentage radius on a wide element gives an ellipse, and a pill is
25
25
  what you wanted.
26
26
 
27
27
  Rounding is the fastest single change to how a system feels, and it is one
28
- token:
28
+ token, but it is the **seed** rather than one of the four above:
29
29
 
30
30
  ```css
31
31
  :root {
32
- --helix-radii-md: 2px;
32
+ --helix-seed-radii: 2px;
33
33
  }
34
34
  ```
35
35
 
36
- That makes every card, dialog, input and button squarer at once. The theme
36
+ That makes every card, dialog, input and button squarer at once, because `sm`,
37
+ `md` and `lg` are all derived from it: they become 1px, 2px and 3px. The theme
37
38
  engine takes a `radius` intent input for exactly this reason. See [Deriving a
38
39
  theme](./theming).
39
40
 
41
+ **Setting `--helix-radii-md` instead moves only what reads `md`**, which is
42
+ neither the buttons, the inputs and the dialogs (`sm`) nor the cards (`lg`).
43
+ The four rungs are siblings derived from the seed, not a chain, so overriding
44
+ one is how you change a single step on purpose rather than how you reshape a
45
+ system.
46
+
47
+ **Every floating panel takes `sm`.** A dialog, a drawer, a menu, a popover, a
48
+ tooltip, a toast, and the panel any field opens under itself: all the same
49
+ corner, whatever the panel's size. A radius is read against the corner beside it
50
+ rather than against the area behind it.
51
+
40
52
  **A shape that is round rather than softened does not use these.** An avatar, a
41
53
  loader and a radio are circles because of what they are, so they say `50%`
42
54
  directly and are unaffected by a theme that squares everything else off.
@@ -59,11 +71,10 @@ belong to [Surfaces and separation](./surfaces-and-separation): they are what a
59
71
  theme sets to zero to go shadow-first, or to a width to go border-first.
60
72
 
61
73
  This distinction is why a component's border width sits behind a per-component
62
- hook rather than being written inline. Of 68 border declarations reaching for
63
- `--helix-color-border` before this was fixed, eight put the *color* behind a
64
- hook and none put the width behind one, so a border could be recoloured and
65
- never removed, and the floating surfaces wrote `border: none` outright so one
66
- could never be added either.
74
+ hook rather than being written inline. A width written inline can be recolored
75
+ by a theme and never removed, and a hardcoded `border: none` can never have one
76
+ added back, so a surface themes perfectly in one direction and not at all in the
77
+ other.
67
78
 
68
79
  ## Corner radius on a group
69
80
 
@@ -49,7 +49,7 @@ Use them for gap, padding and margin:
49
49
 
50
50
  ## Size
51
51
 
52
- Thirty-four tokens, and almost all of them name a specific thing:
52
+ Forty-one tokens, and almost all of them name a specific thing:
53
53
  `--helix-size-control`, `--helix-size-checkbox`, `--helix-size-switch`,
54
54
  `--helix-size-avatar`, `--helix-size-icon`, `--helix-size-tag`,
55
55
  `--helix-size-header`, `--helix-size-progress`, `--helix-size-meter`.
@@ -21,11 +21,11 @@ That works. Type in it and the value moves. Assign to it later and the value
21
21
  moves to what you assigned. There is no mode to be in and nothing to wire before
22
22
  the control responds.
23
23
 
24
- *This page said the opposite until 26 Aug 2026, and the sample above was printed
25
- as plain text with an instruction not to paste it. Writing a property was a
26
- claim of ownership, so the element announced its changes and applied none of
27
- them until it was told, and that markup produced a field that ignored every
28
- keystroke with nothing logged and nothing visibly wrong.*
24
+ *This page said the opposite until 26 Aug 2026: writing a property was a claim
25
+ of ownership, so the element announced its changes and applied none of them
26
+ until it was told. The mode is deleted. If you were refusing a change by
27
+ withholding a state update rather than by calling `preventDefault()`, that is
28
+ the one thing that has to be rewritten.*
29
29
 
30
30
  ## Taking a decision
31
31
 
@@ -39,7 +39,7 @@ because Svelte was already right about custom elements.
39
39
  `bind:` does not work on a Helix control, because there is no two-way binding
40
40
  convention a custom element can opt into. Read the value off the event.
41
41
 
42
- And a declared `value`, `open`, `checked` or `active` is a claim of ownership:
43
- the element announces and waits rather than applying the change itself. Use
44
- `default-value` and its siblings when you want the element to own its own state.
42
+ And a declared `value`, `open`, `checked` or `active` is a seed: the element
43
+ starts there and goes on applying its own changes. To refuse one, cancel the
44
+ matching `helix-before-*` event; withholding a state update refuses nothing.
45
45
  See [State and control](./state-and-control).
@@ -55,7 +55,7 @@ export const theme = { brand: '#2563eb', chroma: { ceiling: 0.1 }, radius: 2 }
55
55
 
56
56
  **Keep the intent, not the tokens.** The tokens are the output of a solver, and
57
57
  the solver improves: a theme stored as its inputs picks up a better derivation,
58
- and a theme stored as 176 literal values is frozen at the version that produced
58
+ and a theme stored as literal values is frozen at the version that produced
59
59
  it. The tokens are for pasting into a system that cannot run the engine.
60
60
 
61
61
  ## What it does not do
@@ -63,7 +63,7 @@ console.log(toCss(theme))
63
63
  ```
64
64
 
65
65
  The emitted block carries the seeds as well as the tokens, so the halves the
66
- engine does not compute, the twenty-four series colours a chart reads, the
66
+ engine does not compute, the twenty-four series colors a chart reads, the
67
67
  spacing scale and the corner radii, re-derive from the same values the solver
68
68
  used. That is what stops the two paths disagreeing on the same page.
69
69
 
package/content/tiers.mdx CHANGED
@@ -15,7 +15,7 @@ direction never reverses.
15
15
  | `@fusion.dev/helix-styles` | Tokens and the base layer. Pure CSS | nothing |
16
16
  | `@fusion.dev/helix-core` | Element base class, mixins, decorators | Lit |
17
17
  | `@fusion.dev/helix-headless` | Structure, accessibility, state, form participation | `core` |
18
- | `@fusion.dev/helix` | Presentation: tokens, parts, and the visual axes | `headless`, `styles` |
18
+ | `@fusion.dev/helix` | Presentation: tokens, parts, and the visual axes | `headless`, `turbo run styles` |
19
19
 
20
20
  `@fusion.dev/helix-theme` and `@fusion.dev/helix-icons` ship beside the stack rather than in it:
21
21
  neither is a tier, and neither is needed to render a component. **There is no
@@ -25,7 +25,7 @@ the bridge that repairs React's hydration of custom events is in
25
25
 
26
26
  ## Why the split
27
27
 
28
- **`headless` must never depend on `styles`.**
28
+ **`headless` must never depend on `turbo run styles`.**
29
29
 
30
30
  That single constraint is what makes the headless tier independently
31
31
  consumable. Consume it and bring your own
@@ -42,10 +42,10 @@ be lifted into: a raised surface goes *down* the ramp, not up.
42
42
  groove.
43
43
 
44
44
  **`raised` and `overlay` are the pair worth learning.** They land on the same
45
- step in dark mode, which is why one token tried to do both jobs for a while. In
46
- light they want opposite fills: a hovered row must be darker than a white page,
47
- and a thumb must be lighter than the groove it sits in. If something looks
48
- almost right in dark and wrong in light, this is usually why.
45
+ step in dark mode, so one token looks like it would do both jobs. In light they
46
+ want opposite fills: a hovered row must be darker than a white page, and a thumb
47
+ must be lighter than the groove it sits in. If something looks almost right in
48
+ dark and wrong in light, this is usually why.
49
49
 
50
50
  ## Per-component hooks
51
51
 
@@ -48,37 +48,37 @@ request and names every document plus these two surfaces.
48
48
 
49
49
  These are in order of how often they look like a library bug and are not.
50
50
 
51
- ### 1. A declared `value` hands you the control
51
+ ### 1. Refusing a change by not answering
52
52
 
53
- ```text
54
- <!-- Ignores every keystroke. Nothing is logged. Nothing looks wrong. -->
55
- <helix-input label="Name" value="Ada"></helix-input>
56
- ```
57
-
58
- Do not paste it. Plain text rather than a live example, the same way
59
- [State and control](./state-and-control) shows this one: a reader copies what is
60
- in front of them, and these are the two pages that have to show the mistake in
61
- order to name it.
62
-
63
- **Writing `value`, `open`, `checked` or `active` is a claim of ownership.** From
64
- then on the element announces changes and applies none of them, waiting to be
65
- told. Which mode it is in is read once, at its first update.
66
-
67
- Seed with the `default-` twin, or answer the event:
53
+ **Writing `value`, `open`, `checked` or `active` is a seed and a correction.**
54
+ The element starts there and goes on applying its own changes, exactly as
55
+ `<input value="Ada">` does, so this works and needs no handler beside it:
68
56
 
69
57
  ```html
70
58
  <helix-input
71
- default-value="Ada"
72
59
  label="Name"
60
+ value="Ada"
73
61
  ></helix-input>
74
62
  ```
75
63
 
64
+ The trap is on the other side. React force-restores a native `<input>` whose
65
+ state did not move and does not do this for a custom element, so a handler that
66
+ declines to call `setState` leaves the element holding the new value. Refusal is
67
+ `preventDefault()` on the matching `helix-before-*` event:
68
+
76
69
  ```tsx
77
- <helix-input label="Name" onChange={(e) => setName(e.currentTarget.value)} value={name} />
70
+ <helix-input
71
+ label="Name"
72
+ onhelix-before-change={(event) => {
73
+ event.preventDefault()
74
+ setName(clean(event.detail.value))
75
+ }}
76
+ value={name}
77
+ />
78
78
  ```
79
79
 
80
- In TypeScript this is a compile error rather than a surprise. Everywhere else the
81
- element warns on its second unanswered request.
80
+ `default-value` and its twins are what a reset returns to. See
81
+ [State and control](./state-and-control).
82
82
 
83
83
  ### 2. The event name is the event's own
84
84
 
@@ -120,10 +120,11 @@ The tell for a missing layer is which. A flash before hydration is
120
120
  `elements.css`; bare headings are `base.css`. **No color anywhere means the
121
121
  ramp or the semantic layer, and the two are told apart by what is in the
122
122
  stylesheet rather than by what is on screen**: without `tokens.css` nothing
123
- declares `--helix-color-*` at all, while without `primitives.css` all 177 are
124
- declared and every one resolves to `rgba(0, 0, 0, 0)`, since `tokens.css` refers
125
- to a primitive 235 times and to nothing else. The second is the one that looks
126
- like a working install, and it is the reason `all.css` exists.
123
+ declares `--helix-color-*` at all, while without `primitives.css` all 185
124
+ semantic tokens are declared and every color resolves to `rgba(0, 0, 0, 0)`,
125
+ since `tokens.css` refers to a primitive 297 times and to nothing else. The
126
+ second is the one that looks like a working install, and it is the reason
127
+ `all.css` exists.
127
128
 
128
129
  ## Choosing a family
129
130
 
@@ -145,9 +146,11 @@ Two distinctions worth knowing before searching:
145
146
 
146
147
  Three doors, in the order to try them.
147
148
 
148
- 1. **A token.** `--helix-radii-md: 2px` at `:root` reaches every component,
149
+ 1. **A token.** `--helix-seed-radii: 2px` at `:root` reaches every component,
149
150
  because custom properties inherit. Most "can I restyle the button" is really
150
- "our brand has less rounding".
151
+ "our brand has less rounding". The seed and not `--helix-radii-md`: the four
152
+ radii are siblings derived from it, so `md` alone moves neither the buttons
153
+ nor the cards.
151
154
  2. **A per-component hook.** `--card-padding` on `helix-card`. Named after the
152
155
  component, documented on its page, defaults to a semantic token.
153
156
  3. **A part.** `helix-select::part(trigger)`. The most powerful and the one that
@@ -189,7 +192,7 @@ for the API.
189
192
 
190
193
  | Tool | Where it goes |
191
194
  |---|---|
192
- | Claude Code | `CLAUDE.md`, or a skill in `.claude/skills/` |
195
+ | Claude Code | `AGENTS.md` or `CLAUDE.md`, or a skill in `.claude/skills/` |
193
196
  | Cursor | `.cursor/rules/` |
194
197
  | GitHub Copilot | `.github/copilot-instructions.md` |
195
198
  | Anything else | Whatever it reads. The line is the same |
@@ -63,8 +63,6 @@ inspecting it.
63
63
  - `onHelixOpen` binds an event called `HelixOpen`, which nobody dispatches. ❌
64
64
 
65
65
  The number of hyphens does not matter, measured in Chrome against React 19.2.8.
66
- An earlier version of this page said two were a hard stop; that was the
67
- hydration bug above, read as a fact about names.
68
66
 
69
67
  ## Register once, in a client component
70
68
 
@@ -29,8 +29,7 @@ vocabularies. You cannot invent a value, and a component may take a subset.
29
29
  ## Why two axes
30
30
 
31
31
  **The library had four axes and one word for all of them.** Counted across both
32
- tiers, `appearance` held 21 declarations describing at least four different
33
- questions: where a surface ends (`outlined` against `plain` on a Card), how much
32
+ tiers, `appearance` described at least four different questions: where a surface ends (`outlined` against `plain` on a Card), how much
34
33
  ink a control claims (`ghost` against `solid` on a Button), which widget gets
35
34
  rendered (`segmented` against `underlined` on Tabs), and in one case a plain
36
35
  misfiled tone.
@@ -45,10 +44,9 @@ and a component reintroducing it fails the build.
45
44
 
46
45
  ## Two axes, not one
47
46
 
48
- This is the test, and the library found it before the registry existed.
49
- `megamenu-root.css` reads: a consumer can make the panel glass, which is not an
50
- appearance, because `full` already occupies that axis with a layout. A panel can
51
- be glass *and* outlined. Two axes.
47
+ This is the test. `Megamenu` is the worked example: a consumer can make the panel
48
+ glass, which is not an appearance, because `full` already occupies that axis with
49
+ a layout. A panel can be glass *and* outlined. Two axes.
52
50
 
53
51
  If you are adding a property and cannot decide which axis it belongs to, that is
54
52
  usually the answer: it is two properties.
@@ -66,7 +64,7 @@ choice between two widgets, which is structural wherever it is made, so it lives
66
64
  on either tier.
67
65
 
68
66
  **What it may not be is a place to put something that is on an axis.** That is
69
- the failure mode `appearance` demonstrated for 21 components.
67
+ the failure mode `appearance` demonstrated.
70
68
 
71
69
  ## `tone` is the one axis both tiers carry
72
70
 
@@ -107,11 +107,10 @@ against the stylesheet's own URL with no bundler involved. Copy the whole
107
107
  four requests and both layers resolve.
108
108
 
109
109
  *This page listed `tokens.css` and `base.css` and no `primitives.css` until 24
110
- Aug 2026, which is the same omission `installation.mdx`, `introduction.mdx` and
111
- the agent page carried. `tokens.css` refers to a primitive 235 times and imports
112
- nothing, so a reader who followed this got all 178 semantic tokens declared and
113
- every one resolving to `rgba(0, 0, 0, 0)`. Linking `all.css` is the fix that
114
- cannot be got wrong again.*
110
+ Aug 2026. `tokens.css` refers to a primitive 297 times and imports nothing, so a
111
+ reader who followed that got all 185 semantic tokens declared and every color
112
+ resolving to `rgba(0, 0, 0, 0)`. If your page looks unstyled in exactly that
113
+ way, link `all.css` instead.*
115
114
 
116
115
  `elements.css` stays its own link, being `@fusion.dev/helix`'s rather than this
117
116
  package's, and it matters more here than anywhere: with no bundler the module
package/dist/catalog.d.ts CHANGED
@@ -2,13 +2,10 @@
2
2
  * The component catalog: manifests and example markup, as one shape a reader
3
3
  * can render.
4
4
  *
5
- * **Pure, and it lives here for the same reason `reference()` does.** This is
6
- * Helix knowledge, and it used to sit in a marketing app: once both an HTML
7
- * page and a `.md` route need it, leaving it there means one of them imports
8
- * across a domain boundary to get at it. Reading the manifests and the
9
- * `.examples/*.html` files off disk is the caller's job, because a content
10
- * package that touched the filesystem would trace itself into every consumer's
11
- * server bundle.
5
+ * **Pure, and it lives here for the same reason `reference()` does.** Reading
6
+ * the manifests and the `.examples/*.html` files off disk is the caller's job,
7
+ * because a content package that touched the filesystem would trace itself
8
+ * into every consumer's server bundle.
12
9
  *
13
10
  * Two sources and no third: the manifests describe the API, and the example
14
11
  * files hold the markup. Nothing about a component is written down here, which
@@ -105,30 +102,24 @@ export interface Example {
105
102
  /**
106
103
  * The same example authored in TSX, which is a file and never a conversion.
107
104
  *
108
- * **Both syntaxes are authored, neither derived.** The sandbox used to run
109
- * the HTML through `htmlToJsx` when a reader asked for TSX, which is the
110
- * mistake `build-headless-examples.mjs` made one axis over and this package
111
- * already rejected once: a derived example is a function of its twin rather
112
- * than a thing anybody wrote. It also did not work. Every example carrying a
113
- * `<script>` converted to a JSX fragment with a `<script>` in it, which is a
114
- * syntax error rather than a bad example, and three separate faults hit the
115
- * script-free ones as well.
105
+ * **Both syntaxes are authored, neither derived.** A derived example is a
106
+ * function of its twin rather than a thing anybody wrote, and converting the
107
+ * HTML mechanically does not work: an example carrying a `<script>` becomes
108
+ * a JSX fragment with a `<script>` in it, which is a syntax error rather
109
+ * than a bad example.
116
110
  *
117
- * `check:examples-paired` holds the two files to each other and
118
- * `check:visual` holds the two pictures to each other.
111
+ * `helix component`'s `examples-paired` holds the two files to each other and
112
+ * `check:spec:visual-parity` holds the two pictures to each other.
119
113
  */
120
114
  tsx: string;
121
115
  /**
122
116
  * Which tier the example shows, read from what it renders.
123
117
  *
124
- * Off the markup rather than off the filename, the same test `check:tokens`
118
+ * Off the markup rather than off the filename, the same test `helix component`'s `tokens`
125
119
  * uses to know a headless example's stylesheet may write raw values: an
126
120
  * example is a headless one when it renders a `helix-headless-` element.
127
- * When this was written the file was called `headless.html` and the name
128
- * could have answered, which is why the comment argued against relying on
129
- * it. Both tiers call theirs `preview.html` now, the package directory
130
- * carrying the tier, so the name cannot answer and this is the only fact
131
- * available. The word `base` was the tier's old name and is gone with it.
121
+ * Both tiers call theirs `preview.html`, the package directory carrying the
122
+ * tier, so the name cannot answer and this is the only fact available.
132
123
  */
133
124
  tier: 'headless' | 'styled';
134
125
  }
@@ -152,22 +143,21 @@ export interface Family {
152
143
  *
153
144
  * An example is up to two files, `<slug>.html` and an optional `<slug>.css`.
154
145
  * The HTML is the list: a stylesheet on its own is not an example, and
155
- * `check:examples` fails on one whose markup is missing rather than showing a
146
+ * `helix component`'s `examples` fails on one whose markup is missing rather than showing a
156
147
  * sandbox with a stylesheet and nothing to style.
157
148
  *
158
149
  * The pair is what the sandbox already shows, `index.html` beside `styles.css`,
159
150
  * so the second file is the one the reader is looking at rather than a build
160
- * step. It is also what replaced the `style` attributes these examples used to
161
- * carry: an inline style is unreachable from a stylesheet, cannot express a
162
- * hover or a media query, and teaches a reader to write the one thing the
163
- * library exists to avoid.
151
+ * step. Never an inline `style` attribute instead: it is unreachable from a
152
+ * stylesheet, cannot express a hover or a media query, and teaches a reader to
153
+ * write the one thing the library exists to avoid.
164
154
  */
165
155
  export interface ExampleSource {
166
156
  css: string;
167
157
  /** Family folder the example was found in. */
168
158
  family: string;
169
159
  html: string;
170
- /** File name without its extension: `default`, `base`, `cards.base`. */
160
+ /** File name without its extension: `preview`, `headless`, `cards.headless`. */
171
161
  slug: string;
172
162
  /** The authored TSX beside the HTML, never a conversion of it. */
173
163
  tsx: string;