@fusion.dev/helix-docs 0.206.0 → 0.207.1

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 (42) hide show
  1. package/README.md +22 -2
  2. package/content/angular.mdx +37 -4
  3. package/content/browser-support.mdx +3 -3
  4. package/content/building-on-the-headless-tier.mdx +84 -21
  5. package/content/charting.mdx +50 -0
  6. package/content/coding-agents.mdx +2 -1
  7. package/content/color-modes.mdx +2 -2
  8. package/content/color.mdx +35 -5
  9. package/content/diagnostics.mdx +255 -0
  10. package/content/graphs.mdx +6 -0
  11. package/content/iconography.mdx +31 -13
  12. package/content/installation.mdx +34 -10
  13. package/content/intent-reference.mdx +27 -3
  14. package/content/introduction.mdx +3 -2
  15. package/content/localization.mdx +86 -4
  16. package/content/maps.mdx +68 -14
  17. package/content/metrics.mdx +252 -249
  18. package/content/other-frameworks.mdx +52 -12
  19. package/content/overriding-a-component.mdx +11 -10
  20. package/content/react.mdx +15 -1
  21. package/content/recipes.mdx +18 -2
  22. package/content/sandbox.mdx +75 -25
  23. package/content/server-rendering.mdx +2 -2
  24. package/content/state-and-control.mdx +7 -1
  25. package/content/surfaces-and-separation.mdx +2 -1
  26. package/content/svelte.mdx +54 -8
  27. package/content/theme-builder.mdx +15 -3
  28. package/content/theming.mdx +5 -1
  29. package/content/tiers.mdx +15 -14
  30. package/content/using-helix-with-an-agent.mdx +12 -5
  31. package/content/using-the-elements.mdx +24 -23
  32. package/content/versioning.mdx +15 -8
  33. package/content/visual-axes.mdx +11 -4
  34. package/content/vue.mdx +28 -1
  35. package/content/without-a-bundler.mdx +9 -7
  36. package/dist/index.d.ts +1 -3
  37. package/dist/index.js +0 -1
  38. package/dist/pages.generated.js +7 -1
  39. package/dist/reference.d.ts +70 -6
  40. package/dist/reference.js +13 -2
  41. package/dist/sources.generated.js +1346 -459
  42. package/package.json +13 -12
@@ -97,8 +97,14 @@ import '@fusion.dev/helix-styles/helix.css'
97
97
  base layer. If you import the layers one at a time, import `elements.css` last.
98
98
 
99
99
  `elements.css` hides each tag with `:not(:defined)` until the element upgrades.
100
- It uses `visibility`, so the page does not reflow. Without it, a card appears as
101
- unstyled text and then jumps into its card layout.
100
+ It uses `visibility`, so a hidden element keeps the size of its unstyled
101
+ content. The layout settles when the elements upgrade and take their own size.
102
+ Without the file, a card appears as unstyled text and then jumps into its card
103
+ layout.
104
+
105
+ A data table that serves its first page as rows is the one element shown before
106
+ it upgrades. `elements.css` lays out those rows as the table draws them. See
107
+ [React](./react).
102
108
 
103
109
  We generate the file from the element sources, and it lists every tag by name.
104
110
  CSS has no selector for any custom element, and a bare `:not(:defined)` would
@@ -116,33 +122,28 @@ use a button.
116
122
 
117
123
  ## Turn off an attribute that is on by default
118
124
 
119
- A boolean attribute is off until you write it, with four exceptions. These are
120
- on until you write the string `"false"`:
121
-
122
- - `modal` on Drawer
123
- - `playsinline` on Video
124
- - `default-pinned` on Chat
125
- - `tab-indents` on Sandbox Source
125
+ A boolean attribute is off until you write it, unless its default is `true`. The
126
+ property table on each component's page shows the default. An attribute whose
127
+ default is `true` stays on until you write the string `"false"`, such as `modal`
128
+ on Drawer:
126
129
 
127
130
  ```html
128
131
  <helix-drawer modal="false"></helix-drawer>
129
132
  ```
130
133
 
131
- In JSX, `modal={false}` sets the property and does the same. Other features
132
- that are on by default turn off with an attribute named `no-`, such as
133
- `no-copy`.
134
+ `"false"` is the only value that turns it off. An empty value, or any other
135
+ string, leaves it on. In JSX, `modal={false}` sets the property and does the
136
+ same. Other features that are on by default turn off with an attribute named
137
+ `no-`, such as `no-copy`.
134
138
 
135
139
  ## Declarative shadow DOM is opt-in
136
140
 
137
- The site ships no declarative shadow DOM (DSD). The shadow styles load with the
138
- element definition. You do not need to configure anything. If you render with
139
- Lit SSR yourself, its declarative shadow DOM hydrates. See
140
- [Server rendering](./server-rendering).
141
-
142
- The site ships no DSD for three reasons:
141
+ The elements need no declarative shadow DOM (DSD). Each element attaches its
142
+ shadow root and loads its styles with its definition, so you do not need to
143
+ configure anything. If you render with Lit SSR yourself, the DSD it writes
144
+ hydrates. See [Server rendering](./server-rendering).
143
145
 
144
- - DSD cannot activate for nodes inserted by script.
145
- - React inserts a server component's output by replaying the flight payload
146
- through DOM APIs, without running the component again.
147
- - The patch that made DSD work hooked into webpack, and Turbopack ignores that
148
- hook without an error.
146
+ DSD does not work in a React server component. React inserts a server
147
+ component's output by replaying the flight payload through DOM APIs, without
148
+ running the component again, and DSD does not activate for nodes that a script
149
+ inserts.
@@ -31,13 +31,13 @@ the same version were tested together.
31
31
 
32
32
  ## The version number comes from the Git tag
33
33
 
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.
34
+ CI computes each version from the Git tags and writes it into every package
35
+ manifest seconds before packing. Once the release is promoted, CI commits the
36
+ same number back to `main`. The `version` in each Helix `package.json` in the
37
+ repository is therefore the last release, and the tag is the record it copies.
36
38
 
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.
39
+ The Rust crates stay at `0.0.0-dev`. The `helix` binary reports the version of
40
+ the npm package it was installed with.
41
41
 
42
42
  Releases use two kinds of tag:
43
43
 
@@ -69,8 +69,15 @@ one of:
69
69
  - `stable`
70
70
  - `deprecated`
71
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.
72
+ Most components are stable. These families are experimental, and their status
73
+ says so:
74
+
75
+ - the spatial charts, which draw in three dimensions
76
+ - Log
77
+ - Strands
78
+ - Motion Toggle
79
+
80
+ We will not change a status to make the library look more finished than it is.
74
81
 
75
82
  ## Release notes
76
83
 
@@ -28,7 +28,7 @@ accept a subset of an axis's values.
28
28
  tone="primary"
29
29
  >Save</helix-button>
30
30
  <helix-card separation="outlined">…</helix-card>
31
- <helix-megamenu material="glass">…</helix-megamenu>
31
+ <helix-drawer material="glass">…</helix-drawer>
32
32
  ```
33
33
 
34
34
  ## Why there is no `appearance` attribute
@@ -52,9 +52,16 @@ build.
52
52
  ## When a property needs two axes
53
53
 
54
54
  **If two values can apply at the same time, they belong on two axes.**
55
- `Megamenu` is the example. `variant="band"` sets the layout of its panel, and
56
- glass is a `material`. A panel can be a band and glass at once, so the two
57
- values sit on two axes. A panel can also be glass and outlined at once.
55
+ `Card` is the example. `separation` sets where its surface ends, and `material`
56
+ sets what fills it. A card can be outlined and glass at once, so the two values
57
+ sit on two axes:
58
+
59
+ ```html
60
+ <helix-card
61
+ material="glass"
62
+ separation="outlined"
63
+ >…</helix-card>
64
+ ```
58
65
 
59
66
  If you are adding a property and cannot decide which axis it belongs on, it is
60
67
  usually two properties.
package/content/vue.mdx CHANGED
@@ -16,6 +16,23 @@ Helix tag in an SFC template has typed props and events. The generated file
16
16
  declares the augmentation under both `vue` and `@vue/runtime-core`, because
17
17
  different tools read different ones.
18
18
 
19
+ ## Report a misspelled prop
20
+
21
+ `vue-tsc` checks the value of each prop a Helix tag declares. By default, it
22
+ does not report a prop name that the tag does not declare, so a misspelled prop
23
+ compiles. To report one, turn on `checkUnknownProps` in `tsconfig.json`:
24
+
25
+ ```json
26
+ {
27
+ "vueCompilerOptions": {
28
+ "checkUnknownProps": true
29
+ }
30
+ }
31
+ ```
32
+
33
+ `strictTemplates` turns it on with the rest of Vue's strict template checks.
34
+ Either option also reports a `data-*` attribute on a Helix tag.
35
+
19
36
  ## Mark Helix tags as custom elements
20
37
 
21
38
  Without this setting, Vue treats `<helix-button>` as a component it cannot find
@@ -70,7 +87,7 @@ work. See [State and control](./state-and-control).
70
87
  <helix-input default-value="Ada" label="Name" />
71
88
 
72
89
  <!-- Mirrored: bind the notification and let the element apply. -->
73
- <helix-input label="Name" @change="name = $event.target.value" />
90
+ <helix-input label="Name" @change="name = ($event.currentTarget as HelixInput).value" />
74
91
 
75
92
  <!-- Refused: you take the decision for this one change. -->
76
93
  <helix-input
@@ -79,3 +96,13 @@ work. See [State and control](./state-and-control).
79
96
  @helix-before-change="$event.preventDefault(); name = clean($event.detail.value)"
80
97
  />
81
98
  ```
99
+
100
+ For a native event such as `change`, `vue-tsc` types `$event.currentTarget` as
101
+ `EventTarget | null`, which has no `value`. The mirrored line casts it to the
102
+ element's class, which you import as a type from the family's subpath:
103
+
104
+ ```vue
105
+ <script setup lang="ts">
106
+ import type { HelixInput } from '@fusion.dev/helix/input'
107
+ </script>
108
+ ```
@@ -32,10 +32,10 @@ own URL. Copy the whole `dist` folder and link `helix.css`. We checked this in
32
32
  Chromium: one `<link>` makes five requests, and every layer resolves.
33
33
 
34
34
  *Until August 24, 2026, this page listed `tokens.css` and `base.css` without
35
- `primitives.css`. `tokens.css` refers to a primitive 297 times and imports
36
- nothing. If you followed the old instructions, all 185 semantic tokens are
37
- declared and every color resolves to `rgba(0, 0, 0, 0)`. If your page looks
38
- unstyled in that way, link `helix.css`.*
35
+ `primitives.css`. `tokens.css` refers to the primitives throughout and imports
36
+ nothing. If you followed the old instructions, every semantic token is declared
37
+ and every color resolves to `rgba(0, 0, 0, 0)`. If your page looks unstyled in
38
+ that way, link `helix.css`.*
39
39
 
40
40
  `elements.css` matters most on a page with no bundler. Without a bundler, the
41
41
  module graph loads over the network, so the markup is on the page longer before
@@ -48,9 +48,11 @@ package made its import relative. Only a bundler resolves a bare specifier in an
48
48
 
49
49
  `@fusion.dev/helix` imports its dependencies by bare specifiers, such as
50
50
  `@fusion.dev/helix-core` and `lit`. A browser resolves a bare specifier only
51
- through an import map, and the elements import 97 separate subpaths of
52
- `@fusion.dev/helix-headless`. An import map would need an entry for each one,
53
- and for each subpath of `lit`.
51
+ through an import map. The elements import a separate subpath of
52
+ `@fusion.dev/helix-headless` for each family, and the package's `exports` maps
53
+ each one to an `index.js` in a folder of its own, so an import map would need an
54
+ entry for each one. A subpath of `lit` is the path of its file, so one `"lit/"` entry
55
+ covers all of them.
54
56
 
55
57
  To use the elements, load them through a bundler, as
56
58
  [Installation](./installation) shows. A CDN that rewrites bare specifiers into
package/dist/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- export type { ApiMember, Element, EventDoc, Example, ExampleSource, Family, PropertyDoc, } from '@fusion.dev/helix-cem';
2
- export { catalog, displayName, findInCatalog, place, startCase, tierOf, } from '@fusion.dev/helix-cem';
3
- export { type ReferenceFamily, type ReferenceOptions, reference, referenceFamilies, } from './reference.js';
1
+ export { type ReferenceFamily, type ReferenceManifest, type ReferenceOptions, reference, referenceFamilies, } from './reference.js';
4
2
  export { contentPath, type DocNavPage, type DocNavSection, type DocPage, type DocSection, findPage, navigation, pages, sections, } from './registry.js';
5
3
  export { findSection } from './sections.js';
6
4
  export { docSources } from './sources.generated.js';
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export { catalog, displayName, findInCatalog, place, startCase, tierOf, } from '@fusion.dev/helix-cem';
2
1
  export { reference, referenceFamilies, } from './reference.js';
3
2
  export { contentPath, findPage, navigation, pages, sections, } from './registry.js';
4
3
  export { findSection } from './sections.js';
@@ -62,6 +62,12 @@ export const docPages = [
62
62
  slug: 'composition',
63
63
  title: 'Composition',
64
64
  },
65
+ {
66
+ description: 'Find the Helix mistakes the browser accepts without an error, on your running pages and in your code, with a setup for Vite, React, Next.js, and CI.',
67
+ section: 'Tooling',
68
+ slug: 'diagnostics',
69
+ title: 'Diagnostics',
70
+ },
65
71
  {
66
72
  description: 'The layer, shadow, and material tokens for stacking, lifting, and translucent surfaces.',
67
73
  section: 'Foundations',
@@ -113,7 +119,7 @@ export const docPages = [
113
119
  title: 'Introduction',
114
120
  },
115
121
  {
116
- description: 'Set the locale of date, time, and number controls, translate the built-in words, and lay out pages right to left.',
122
+ description: 'Set the locale of date, time, and number controls, translate the built-in words, lay out pages right to left, and color a rise and a fall for your market.',
117
123
  section: 'Essentials',
118
124
  slug: 'localization',
119
125
  title: 'Localization and RTL',
@@ -21,12 +21,76 @@
21
21
  * prose under a heading, and truncating that threw away everything `Date
22
22
  * Picker` says about its three modes.
23
23
  */
24
- import type { HelixDeclaration, HelixManifest } from '@fusion.dev/helix-cem';
24
+ /** An entry of one of a declaration's lists, as much as the reference prints. */
25
+ export interface ReferenceEntry {
26
+ description?: string;
27
+ /** The class it came from, where the element inherited it. */
28
+ inheritedFrom?: {
29
+ name: string;
30
+ };
31
+ name: string;
32
+ type?: {
33
+ text?: string;
34
+ };
35
+ }
36
+ /** A field or a method. */
37
+ export interface ReferenceMember extends ReferenceEntry {
38
+ default?: string;
39
+ kind?: string;
40
+ privacy?: string;
41
+ }
42
+ /** An element, as much of one as the reference prints. */
43
+ export interface ReferenceDeclaration {
44
+ /** `fieldName` pairs an attribute with the property it sets. */
45
+ attributes?: Array<{
46
+ fieldName?: string;
47
+ name: string;
48
+ }>;
49
+ cssParts?: ReferenceEntry[];
50
+ cssProperties?: ReferenceEntry[];
51
+ cssStates?: ReferenceEntry[];
52
+ description?: string;
53
+ events?: ReferenceEntry[];
54
+ /** The family the element joins from another package, from `@family`. */
55
+ helix?: {
56
+ family?: string;
57
+ };
58
+ members?: ReferenceMember[];
59
+ slots?: ReferenceEntry[];
60
+ summary?: string;
61
+ superclass?: {
62
+ name: string;
63
+ };
64
+ tagName?: string;
65
+ }
66
+ /** A `custom-elements.json`, as much of one as the reference reads. */
67
+ export interface ReferenceManifest {
68
+ modules?: Array<{
69
+ declarations?: ReferenceDeclaration[];
70
+ path?: string;
71
+ }>;
72
+ }
73
+ /** `app-header` becomes `App Header`, and `qr-code` becomes `QR Code`. */
74
+ export declare const startCase: (slug: string) => string;
75
+ /** The family and part a declaration belongs to, from where its file is. */
76
+ export declare const place: (path: string | undefined) => {
77
+ family: string;
78
+ part: string;
79
+ };
80
+ /**
81
+ * The family a declaration belongs to: the one its `@family` names, and the
82
+ * one its folder names where it names none.
83
+ */
84
+ export declare const familyOf: (declaration: {
85
+ helix?: {
86
+ family?: string;
87
+ };
88
+ }, path: string | undefined) => string;
25
89
  /**
26
90
  * An example, as much of one as a markdown reference prints.
27
91
  *
28
- * Structural rather than the catalog's `Example`, so this module does not
29
- * import from one that imports it. Anything the catalog returns satisfies it.
92
+ * Structural rather than the catalog's `Example`, which is
93
+ * `@fusion.dev/helix-cem`'s. Anything the catalog returns satisfies it.
30
94
  */
31
95
  export interface ReferenceExample {
32
96
  css: string;
@@ -80,7 +144,7 @@ export interface ReferenceOptions {
80
144
  export interface ReferenceFamily {
81
145
  family: string;
82
146
  parts: Array<{
83
- declaration: HelixDeclaration;
147
+ declaration: ReferenceDeclaration;
84
148
  part: string;
85
149
  }>;
86
150
  }
@@ -91,7 +155,7 @@ export interface ReferenceFamily {
91
155
  * the thing that holds the others, and `item` before `root` is alphabetical
92
156
  * order telling you about the alphabet rather than about the component.
93
157
  */
94
- export declare const referenceFamilies: (manifest: HelixManifest) => ReferenceFamily[];
158
+ export declare const referenceFamilies: (manifest: ReferenceManifest) => ReferenceFamily[];
95
159
  /**
96
160
  * A manifest, as the markdown reference for everything in it.
97
161
  *
@@ -103,4 +167,4 @@ export declare const referenceFamilies: (manifest: HelixManifest) => ReferenceFa
103
167
  * does: a document about the accordion should not say Accordion twice before
104
168
  * its first sentence. More than one and the headings are what separate them.
105
169
  */
106
- export declare const reference: (manifest: HelixManifest, options?: ReferenceOptions) => string;
170
+ export declare const reference: (manifest: ReferenceManifest, options?: ReferenceOptions) => string;
package/dist/reference.js CHANGED
@@ -1,4 +1,14 @@
1
- import { place, startCase } from '@fusion.dev/helix-cem';
1
+ const INITIALISMS = new Set(['api', 'css', 'html', 'id', 'qr', 'ui', 'url']);
2
+ export const startCase = (slug) => slug
3
+ .split('-')
4
+ .filter(Boolean)
5
+ .map((word) => INITIALISMS.has(word) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1))
6
+ .join(' ');
7
+ export const place = (path) => {
8
+ const [, family = '', part = ''] = /^src\/([^/]+)\/([^/]+)\//.exec(path ?? '') ?? [];
9
+ return { family, part };
10
+ };
11
+ export const familyOf = (declaration, path) => declaration.helix?.family ?? place(path).family;
2
12
  const INFRASTRUCTURE = new Set(['HelixElement']);
3
13
  const isPublic = (member) => member.privacy !== 'private' &&
4
14
  member.privacy !== 'protected' &&
@@ -21,10 +31,11 @@ export const referenceFamilies = (manifest) => {
21
31
  if (!declaration.tagName) {
22
32
  continue;
23
33
  }
24
- const { family, part } = place(module.path);
34
+ const family = familyOf(declaration, module.path);
25
35
  if (!family) {
26
36
  continue;
27
37
  }
38
+ const { part } = place(module.path);
28
39
  families.set(family, [...(families.get(family) ?? []), { declaration, part }]);
29
40
  }
30
41
  }