@fusion.dev/helix-docs 0.0.0-dev → 0.0.2
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/browser-support.mdx +2 -2
- package/content/charting.mdx +4 -8
- package/content/coding-agents.mdx +14 -22
- package/content/color-modes.mdx +4 -4
- package/content/color.mdx +2 -2
- package/content/elevation-and-material.mdx +2 -2
- package/content/events.mdx +1 -1
- package/content/forms.mdx +5 -7
- package/content/iconography.mdx +15 -12
- package/content/installation.mdx +4 -6
- package/content/introduction.mdx +1 -1
- package/content/metrics.mdx +214 -214
- package/content/other-frameworks.mdx +6 -5
- package/content/overriding-a-component.mdx +11 -15
- package/content/routing.mdx +4 -4
- package/content/server-rendering.mdx +1 -1
- package/content/shape-and-borders.mdx +19 -8
- package/content/space-and-size.mdx +1 -1
- package/content/state-and-control.mdx +5 -5
- package/content/svelte.mdx +3 -3
- package/content/theme-builder.mdx +1 -1
- package/content/theming.mdx +1 -1
- package/content/tiers.mdx +2 -2
- package/content/tokens.mdx +4 -4
- package/content/using-helix-with-an-agent.mdx +30 -27
- package/content/using-the-elements.mdx +0 -2
- package/content/visual-axes.mdx +5 -7
- package/content/without-a-bundler.mdx +4 -5
- package/dist/catalog.d.ts +19 -29
- package/dist/catalog.js +27 -49
- package/dist/naming.js +1 -1
- package/dist/pages.generated.d.ts +1 -1
- package/dist/pages.generated.js +1 -1
- package/dist/reference.js +1 -1
- package/dist/registry.d.ts +3 -3
- package/dist/registry.js +3 -3
- package/dist/sections.d.ts +3 -7
- package/dist/sections.js +3 -7
- package/dist/sources.generated.d.ts +2 -2
- package/dist/sources.generated.js +367 -374
- 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
|
|
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.
|
|
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.
|
|
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
|
|
81
|
-
nothing is valid CSS that matches nothing and reports nothing.
|
|
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. `
|
|
109
|
-
rendered one to each other, and `
|
|
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.
|
|
112
|
-
|
|
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.
|
package/content/routing.mdx
CHANGED
|
@@ -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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
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
|
|
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
|
|
32
|
+
--helix-seed-radii: 2px;
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
That makes every card, dialog, input and button squarer at once
|
|
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.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
package/content/svelte.mdx
CHANGED
|
@@ -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
|
|
43
|
-
|
|
44
|
-
`
|
|
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
|
|
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
|
package/content/theming.mdx
CHANGED
|
@@ -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
|
|
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
|
package/content/tokens.mdx
CHANGED
|
@@ -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,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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.
|
|
51
|
+
### 1. Refusing a change by not answering
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
|
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
|
-
|
|
81
|
-
|
|
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
|
|
124
|
-
declared and every
|
|
125
|
-
to a primitive
|
|
126
|
-
like a working install, and it is the reason
|
|
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
|
|
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
|
|
package/content/visual-axes.mdx
CHANGED
|
@@ -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`
|
|
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
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
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
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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.**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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.**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* than 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
|
-
* `
|
|
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 `
|
|
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
|
-
*
|
|
128
|
-
*
|
|
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
|
-
* `
|
|
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.
|
|
161
|
-
*
|
|
162
|
-
*
|
|
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: `
|
|
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;
|