@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.
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
@@ -28,11 +28,11 @@ report we want, and it is not one we would have caught.
28
28
  | Custom elements and shadow DOM | Everything |
29
29
  | `ElementInternals` | Form participation, and ARIA that has to cross a shadow boundary |
30
30
  | Popover API | Every overlay: menu, tooltip, select, combobox, dialog |
31
- | `light-dark()` | 761 declarations, 135 of them in the token layer |
31
+ | `light-dark()` | 156 declarations in the shipped stylesheets, 71 of them in the token layer |
32
32
  | `oklch()` | Every color in the system |
33
33
  | `:has()` | 11 rules, mostly relational styling of slotted content |
34
34
  | `@starting-style` | Entry transitions on overlays |
35
- | `:state()` | Every boolean state the library publishes: `open`, `checked`, `selected`, `invalid`, `read`, `has-label`, `settled`, `empty` |
35
+ | `:state()` | Every boolean state the library publishes: `open`, `checked`, `selected`, `invalid`, `read`, `has-label`, `settled`, `empty`, `controls` |
36
36
  | `CSS.highlights` | Filter-match highlighting, in `Command` and `Combobox` |
37
37
 
38
38
  Positioning is `@floating-ui/dom` rather than CSS anchor positioning, which is a
@@ -52,18 +52,14 @@ Hide the table visually if it should not be seen, and the data is still there:
52
52
  The caption becomes the chart's accessible name unless you set `label`, which is
53
53
  usually the right words and is already written.
54
54
 
55
- ## Series colours
55
+ ## Series colors
56
56
 
57
57
  Twenty-four `--helix-color-series-*` tokens, in order. A chart with three series
58
58
  uses the first three. They are ordered to stay distinguishable in that order
59
59
  rather than to look good as a full set of twenty-four.
60
60
 
61
- The palette wraps, and where it wraps is one number in one place. It used to be
62
- four: four families held the same `const PALETTE = 24` and the legend held a
63
- fifth, so when the palette went from eight to twenty-four one of them was missed
64
- and drew every ninth series in the first color while the legend beside it named
65
- the ninth correctly. A number two files have to agree on is a number that will
66
- stop agreeing.
61
+ The palette wraps, and where it wraps is one number in one place, so a chart and
62
+ the legend beside it can never disagree about which color a series is.
67
63
 
68
64
  **A chart's mark carries its own series color as a custom property**, because a
69
65
  chart knows which series a bar belongs to and CSS cannot count it. That is what
@@ -76,7 +72,7 @@ lets you restyle a series from outside without knowing the drawing order.
76
72
  <helix-bar-chart for="revenue"></helix-bar-chart>
77
73
  ```
78
74
 
79
- The legend reads the same table, so the names and the colours cannot disagree
75
+ The legend reads the same table, so the names and the colors cannot disagree
80
76
  with the chart's. Pointing them at two different tables is the only way to make
81
77
  them disagree, and it is not something to do by accident.
82
78
 
@@ -18,13 +18,9 @@ https://fusion.dev/helix/custom-elements.json
18
18
  @fusion.dev/helix/custom-elements.json
19
19
  ```
20
20
 
21
- A URL and a package path, the same file either way. **The URL exists because this
22
- page's own argument required it**: an agent that found the library through
23
- `llms.txt` has this site and no checkout, and a specifier is reachable from a
24
- `node_modules` and from nowhere else. It was only the specifier until 24 Aug 2026,
25
- and the specifier did not resolve either: `exports` carried a `./*` pattern
26
- pointing at `./dist/*/index.js`, so the path two pages recommended was one
27
- `require.resolve` refused.
21
+ A URL and a package path, the same file either way. **Both exist because a
22
+ specifier is reachable from a `node_modules` and from nowhere else**, and an
23
+ agent that found the library through `llms.txt` has this site and no checkout.
28
24
 
29
25
  Every element, every property with its literal type union, every event with its
30
26
  class, every slot, every part, every custom property. It is what the framework
@@ -62,13 +58,13 @@ These are the difference between code that looks right and code that passes:
62
58
 
63
59
  | Rule | Check |
64
60
  |---|---|
65
- | A dispatched event must be declared | `check:events` |
66
- | A documented part must be rendered | `check:parts` |
67
- | A documented CSS hook must be read | `check:hooks` |
68
- | A visual property draws from its axis | `check:axes` |
69
- | A form control styles with `:disabled` | `check:disabled` |
70
- | A component that animates answers reduced motion | `check:motion` |
71
- | No component reads a primitive token | `check:tokens` |
61
+ | A dispatched event must be declared | `helix component --only events` |
62
+ | A documented part must be rendered | `helix component`'s `parts` |
63
+ | A documented CSS hook must be read | `helix component --only hooks` |
64
+ | A visual property draws from its axis | `helix component`'s `axes` |
65
+ | A form control styles with `:disabled` | `helix component --only disabled` |
66
+ | A component that animates answers reduced motion | `helix component --only motion` |
67
+ | No component reads a primitive token | `helix component`'s `tokens` |
72
68
 
73
69
  If you are generating Helix code, the first two are the ones that produce
74
70
  working-looking output that is wrong.
@@ -86,8 +82,7 @@ existing.
86
82
 
87
83
  Start there rather than crawling: one request, and it names every page on the
88
84
  site plus the two machine-readable surfaces above. No count here, because a
89
- number typed into prose is a number that goes stale, which the read of these pages
90
- on 24 Aug 2026 found five of.
85
+ number typed into prose is a number that goes stale.
91
86
 
92
87
  ## From a component's page
93
88
 
@@ -127,12 +122,9 @@ of a binary you installed, talking to a client you chose, with no network in it.
127
122
  page into one file is out of date the moment anything changes, where the links
128
123
  in `llms.txt` are individually cacheable and individually current.
129
124
 
130
- This page used to offer one anyway, a repository path to a generated document
131
- holding every family at once, which contradicted the paragraph above it and was
132
- not a thing a consumer could open: an agent reading the published package has
133
- this site and no checkout. What it was for is covered better by the two surfaces
134
- already here. `llms.txt` is the index, one request, and each family's `.md` is
135
- the document. Fetch the families you are using.
125
+ What such a file would be for is covered better by the two surfaces already
126
+ here. `llms.txt` is the index, one request, and each family's `.md` is the
127
+ document. Fetch the families you are using.
136
128
 
137
129
  **A search index.** The site has one for humans; there is nothing an agent can
138
130
  query yet, and `llms.txt` plus the documents it names is a smaller thing to read
@@ -20,9 +20,9 @@ stylesheet, no `.dark` class to toggle, and nothing to remember to update twice.
20
20
 
21
21
  Every token is written once, with both halves in a `light-dark()`. Which half
22
22
  resolves is decided by `color-scheme` and nothing else, so the mode is a single
23
- inherited property and no token is restated to honor it. That is 761
24
- declarations across the library, 135 of them in the token layer, expressing two
25
- modes without a second copy of anything.
23
+ inherited property and no token is restated to honor it. That is 156
24
+ declarations across the shipped stylesheets, 71 of them in the token layer,
25
+ expressing two modes without a second copy of anything.
26
26
 
27
27
  ## Setting the mode
28
28
 
@@ -72,7 +72,7 @@ told.
72
72
 
73
73
  ## What this means for your own CSS
74
74
 
75
- Write `light-dark()` for your own colours and set nothing else:
75
+ Write `light-dark()` for your own colors and set nothing else:
76
76
 
77
77
  ```css
78
78
  .callout {
package/content/color.mdx CHANGED
@@ -6,7 +6,7 @@ title: Color
6
6
 
7
7
  # Color
8
8
 
9
- Seventy-four of the library's 177 tokens are color, which is most of what a
9
+ Seventy-four of the library's 185 tokens are color, which is most of what a
10
10
  theme is. They are roles rather than values: nothing in Helix is named after
11
11
  what it looks like, because a name like `--brand-blue-500` stops being true the
12
12
  moment anybody rethemes.
@@ -81,7 +81,7 @@ pairing a reader has to be able to read.
81
81
  /* Yours to read. */
82
82
  color: var(--helix-color-foreground-muted);
83
83
 
84
- /* Not yours to read, and `check:tokens` fails the build on it. */
84
+ /* Not yours to read, and the `tokens` rule fails the build on it. */
85
85
  color: var(--_helix-neutral-500);
86
86
  ```
87
87
 
@@ -70,8 +70,8 @@ Eight tokens describing translucency rather than color:
70
70
  | `--helix-material-blur-sm` | `8px` | The lightest backdrop blur. |
71
71
  | `--helix-material-blur-md` | `16px` | The backdrop blur a modal takes. |
72
72
  | `--helix-material-blur-lg` | `32px` | The heaviest backdrop blur. |
73
- | `--helix-material-translucent` | `color-mix(in oklab, light-dark(oklch(1 0 0), oklch(0.21 var(--helix-seed-neutral-chroma, 0) var(--helix-seed-neutral-hue, 258))) 30%, transparent)` | The translucent ground, for a surface that admits what is behind it. |
74
- | `--helix-material-translucent-strong` | `color-mix(in oklab, light-dark(oklch(1 0 0), oklch(0.21 var(--helix-seed-neutral-chroma, 0) var(--helix-seed-neutral-hue, 258))) 88%, transparent)` | The heavier translucent ground, for one that admits less. |
73
+ | `--helix-material-translucent` | `color-mix(in oklab, light-dark(oklch(1 0 0), oklch(0.182 var(--helix-seed-neutral-chroma, 0) var(--helix-seed-neutral-hue, 258))) 30%, transparent)` | The translucent ground, for a surface that admits what is behind it. |
74
+ | `--helix-material-translucent-strong` | `color-mix(in oklab, light-dark(oklch(1 0 0), oklch(0.182 var(--helix-seed-neutral-chroma, 0) var(--helix-seed-neutral-hue, 258))) 88%, transparent)` | The heavier translucent ground, for one that admits less. |
75
75
  | `--helix-material-border` | `light-dark(color-mix(in oklab, oklch(0.15 var(--helix-seed-neutral-chroma, 0) var(--helix-seed-neutral-hue, 258)) 14%, transparent), color-mix(in oklab, oklch(1 0 0) 12%, transparent))` | The edge a translucent surface needs to have any at all. |
76
76
 
77
77
  [//]: # (/tokens)
@@ -103,7 +103,7 @@ dispatch, so an event you can listen for is an event that is documented.
103
103
  | `helix-navigate` | A component is about to navigate |
104
104
  | `helix-copy` | Something was copied |
105
105
  | `helix-caret` | The cursor moved in a text control |
106
- | `helix-load`, `helix-error`, `helix-complete` | Media and async lifecycle |
106
+ | `helix-complete` | A control that fills up has filled |
107
107
  | `helix-create` | A new item was made from a query |
108
108
  | `helix-console` | The sandbox relaying a log |
109
109
  | `helix-tour-ask`, `helix-sample-start`, `helix-sample-end` | Tour and color sampling |
package/content/forms.mdx CHANGED
@@ -94,7 +94,7 @@ Submitting an empty form blocks and points at the control. `checkValidity()`,
94
94
  `reportValidity()` and `:invalid` behave.
95
95
 
96
96
  **`feedback` overrides the message.** Left empty, the browser's own is shown,
97
- which is localised and familiar; set, it says what you want in the words your
97
+ which is localized and familiar; set, it says what you want in the words your
98
98
  product uses:
99
99
 
100
100
  ```html
@@ -123,12 +123,10 @@ deliberately reports no value of its own.
123
123
  </fieldset>
124
124
  ```
125
125
 
126
- That works, and it did not always. The platform tells a form-associated element
127
- through `formDisabledCallback`, which nothing implemented, so a control inside a
128
- disabled fieldset stayed fully typeable and announced itself as enabled.
129
- Measured: a `helix-input` in one accepted text, reported `disabled` as false,
130
- and carried no `aria-disabled`, while the form's entry list correctly left it
131
- out. Interactive and unsubmittable is the worst of both.
126
+ That works. The platform tells a form-associated element it has been disabled by
127
+ an ancestor through `formDisabledCallback`, and every Helix control implements
128
+ it, so a control inside a disabled fieldset refuses input and announces itself
129
+ as off rather than staying typeable and unsubmittable.
132
130
 
133
131
  **For your own CSS this means one rule.** Style disabled controls with
134
132
  `:disabled`, never `[disabled]`:
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: 103 glyphs, one geometry, and how to draw one that is not in the set.
2
+ description: 105 glyphs, one geometry, and how to draw one that is not in the set.
3
3
  section: Foundations
4
4
  title: Iconography
5
5
  ---
@@ -10,10 +10,12 @@ title: Iconography
10
10
  <helix-icon name="trash"></helix-icon>
11
11
  ```
12
12
 
13
- 103 glyphs, from Phosphor, drawn on a 256 box at stroke-width 16. That is
13
+ 105 glyphs, from Phosphor, drawn on a 256 box at Phosphor's bold weight. That is
14
14
  Phosphor's own geometry and it is kept rather than rescaled: normalizing to a 24
15
15
  box would change the optical weight of every glyph and stop the set matching
16
- anything upstream.
16
+ anything upstream. Bold rather than regular, because Phosphor's regular is a
17
+ hairline beside the medium weight this library sets its text in, and an icon
18
+ that reads lighter than the words next to it is the opposite of a mark.
17
19
 
18
20
  ## Size and color come from the context
19
21
 
@@ -63,18 +65,19 @@ failure rather than an empty box.
63
65
 
64
66
  ## Adding one
65
67
 
66
- Drop the SVG into `helix/icons/raw` and run `bun run icons`. The set is
67
- generated from those files, so adding a glyph is adding a file rather than
68
- hand-transcribing a path into a TypeScript object.
68
+ Add the name to `helix/icons/icons.txt` and run `turbo run icons`. Phosphor names
69
+ resolve from `@phosphor-icons/core` at build time, so adding a glyph is adding a
70
+ line rather than hand-transcribing a path into a TypeScript object.
69
71
 
70
- Keep to the same geometry: 256 box, stroke-width 16, no fill. A glyph drawn at a
71
- different weight is visible immediately when it sits beside one that was not.
72
+ A mark Phosphor does not draw goes into `helix/icons/raw` as an SVG under the
73
+ same name, and is read from there when the package has no match. Keep it to the
74
+ same geometry, a 256 box at the bold weight: a glyph drawn at a different weight
75
+ is visible immediately when it sits beside one that was not.
72
76
 
73
77
  ## Icons this set does not have
74
78
 
75
79
  Product marks. Helix and Cortex have marks and they live in the icon package,
76
80
  but a mark is not an icon: it identifies a product and does not mean an action.
77
- Three earlier attempts at product marks were removed for being pictograms of a
78
- metaphor standing beside a parent that is a geometric monogram, and the rule
79
- that replaced them is that **a mark is one rounded body with material removed**.
80
- If you are reaching for the icon set to draw a logo, that is the wrong drawer.
81
+ **A mark is one rounded body with material removed**, never a pictogram of a
82
+ metaphor, because the parent it stands beside is a geometric monogram. If you
83
+ are reaching for the icon set to draw a logo, that is the wrong drawer.
@@ -24,8 +24,7 @@ import '@fusion.dev/helix/helix.css'
24
24
 
25
25
  One import, and it is four files in the order they have to be in:
26
26
  `primitives.css`, `tokens.css`, `base.css`, `elements.css`. The order is
27
- load-bearing and the failure is silent, which these instructions demonstrated
28
- for longer than anyone would like, so it is stated once inside the package
27
+ load-bearing and the failure is silent, so it is stated once inside the package
29
28
  rather than by every consumer.
30
29
 
31
30
  It resolves `@fusion.dev/helix-styles` through this package's own dependency, so
@@ -41,13 +40,12 @@ own ramp imports the two they want and skips the bundle.
41
40
  - **`primitives.css`** is the raw ramp the semantic layer is derived from, and
42
41
  it is where the seven `--helix-seed-*` knobs are read. Nothing in your own
43
42
  code should name a primitive, and leaving the file out is not a way to
44
- enforce that: `tokens.css` refers to one 235 times, so without it every
43
+ enforce that: `tokens.css` refers to one 297 times, so without it every
45
44
  semantic token resolves to nothing at all. Measured on a page missing it,
46
45
  `--helix-color-background` computes to `rgba(0, 0, 0, 0)`, and so does every
47
46
  other color. It is also the file [theming](theming.mdx) depends on, since a
48
- `--helix-seed-brand` nobody reads moves nothing. **This is the one that was
49
- missing from this page**, which is why the bundle exists.
50
- - **`tokens.css`** declares the semantic layer, 177 custom properties in 15
47
+ `--helix-seed-brand` nobody reads moves nothing.
48
+ - **`tokens.css`** declares the semantic layer, 185 custom properties in 15
51
49
  categories, plus `color-scheme: light dark` on `:root`. Everything below reads
52
50
  from it, and it reads primitives.
53
51
  - **`base.css`** is the element reset, the type scale on bare `h1` through
@@ -30,7 +30,7 @@ analysis time rather than left to review.
30
30
  bun add @fusion.dev/helix @fusion.dev/helix-styles
31
31
  ```
32
32
 
33
- Three imports at your app root, in this order, then the elements are usable
33
+ Two imports at your app root, in this order, then the elements are usable
34
34
  anywhere:
35
35
 
36
36
  ```ts