@fusion.dev/helix-templates 0.139.0 → 0.140.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/package.json +1 -1
  2. package/templates/angular/src/app/data.ts +17 -17
  3. package/templates/angular/src/app/docs.ts +9 -9
  4. package/templates/angular/src/app/landing.html +36 -71
  5. package/templates/angular/src/app/landing.ts +0 -2
  6. package/templates/angular/src/app/overview.html +2 -2
  7. package/templates/angular/src/app/pathname.ts +1 -1
  8. package/templates/angular/src/app/signup-form.html +9 -10
  9. package/templates/angular/src/app/site-footer.html +1 -1
  10. package/templates/angular/src/app/site-header.ts +2 -3
  11. package/templates/angular/src/app.css +144 -152
  12. package/templates/react-nextjs/app/app.css +144 -152
  13. package/templates/react-nextjs/app/data.ts +17 -17
  14. package/templates/react-nextjs/app/docs.ts +9 -9
  15. package/templates/react-nextjs/app/landing.tsx +63 -121
  16. package/templates/react-nextjs/app/overview.tsx +24 -26
  17. package/templates/react-nextjs/app/signup-form.tsx +36 -39
  18. package/templates/react-nextjs/app/site-footer.tsx +7 -10
  19. package/templates/react-nextjs/app/site-header.tsx +17 -21
  20. package/templates/react-nextjs/helix-jsx.d.ts +5 -7
  21. package/templates/react-vite/helix-jsx.d.ts +5 -7
  22. package/templates/react-vite/src/app.css +144 -152
  23. package/templates/react-vite/src/data.ts +17 -17
  24. package/templates/react-vite/src/docs.ts +9 -9
  25. package/templates/react-vite/src/landing.tsx +63 -121
  26. package/templates/react-vite/src/overview.tsx +24 -26
  27. package/templates/react-vite/src/routes.tsx +11 -13
  28. package/templates/react-vite/src/signup-form.tsx +36 -39
  29. package/templates/react-vite/src/site-footer.tsx +7 -10
  30. package/templates/react-vite/src/site-header.tsx +15 -19
  31. package/templates/solid-vite/src/app.css +144 -152
  32. package/templates/solid-vite/src/data.ts +17 -17
  33. package/templates/solid-vite/src/docs.ts +9 -9
  34. package/templates/solid-vite/src/landing.tsx +51 -98
  35. package/templates/solid-vite/src/overview.tsx +2 -2
  36. package/templates/solid-vite/src/routes.ts +6 -6
  37. package/templates/solid-vite/src/signup-form.tsx +10 -10
  38. package/templates/solid-vite/src/site-footer.tsx +1 -1
  39. package/templates/solid-vite/src/site-header.tsx +2 -3
  40. package/templates/svelte-vite/src/Landing.svelte +36 -73
  41. package/templates/svelte-vite/src/Overview.svelte +2 -2
  42. package/templates/svelte-vite/src/SignupForm.svelte +9 -10
  43. package/templates/svelte-vite/src/SiteFooter.svelte +1 -1
  44. package/templates/svelte-vite/src/SiteHeader.svelte +2 -3
  45. package/templates/svelte-vite/src/app.css +144 -152
  46. package/templates/svelte-vite/src/data.ts +17 -17
  47. package/templates/svelte-vite/src/docs.ts +9 -9
  48. package/templates/svelte-vite/src/routes.svelte.ts +5 -5
  49. package/templates/vue-vite/src/LandingPage.vue +36 -73
  50. package/templates/vue-vite/src/OverviewPage.vue +2 -2
  51. package/templates/vue-vite/src/SignupForm.vue +10 -10
  52. package/templates/vue-vite/src/SiteFooter.vue +1 -1
  53. package/templates/vue-vite/src/SiteHeader.vue +2 -3
  54. package/templates/vue-vite/src/app.css +144 -152
  55. package/templates/vue-vite/src/data.ts +17 -17
  56. package/templates/vue-vite/src/docs.ts +9 -9
  57. package/templates/vue-vite/src/routes.ts +6 -6
@@ -14,8 +14,6 @@ const figure = new Intl.NumberFormat('en-US')
14
14
  * Delete it once you know your way around: nothing else imports it, and the
15
15
  * route it answers becomes yours.
16
16
  *
17
- * **The heading says what this is, and the project's name stays in the bar.**
18
- *
19
17
  * **The calls to action are anchors.** A button that navigates is a link
20
18
  * dressed as a button, and the two are different things to a keyboard and to
21
19
  * a screen reader. The base stylesheet styles an anchor that asks with
@@ -25,15 +23,20 @@ export function Landing() {
25
23
  return (
26
24
  <div class="stack">
27
25
  <header class="first-screen">
26
+ {/* **The light behind the first screen**: a helix, drawn by the library
27
+ in the theme's colors, so a new brand color relights it. It shows
28
+ one still frame where motion is reduced, and a gradient where the
29
+ browser draws without a GPU. */}
30
+ <helix-aura class="first-light" data-layer speed={0.4} terminus={0.8} variant="braid" />
28
31
  <div class="hero">
29
- <helix-text emphasis="muted" variant="label">
30
- Helix starter
32
+ <helix-tag emphasis="subtle" tone="primary">
33
+ Starter
34
+ </helix-tag>
35
+ <helix-text as="h1" variant="display">
36
+ Helix design system
31
37
  </helix-text>
32
- <helix-text as="h1">Every tag on this page is Helix</helix-text>
33
- <helix-text as="p" class="lede" emphasis="muted" variant="body">
34
- Nothing here is a wrapper: the tags are the library's own elements, and every color,
35
- size and space inside them comes from one set of tokens. Three routes are laid down, and
36
- all of them are yours.
38
+ <helix-text as="p" class="lede" variant="body">
39
+ Web components in your brand's colors, drawn from one set of tokens.
37
40
  </helix-text>
38
41
  <div class="actions">
39
42
  <a data-button="solid" data-button-tone="primary" href="#/overview">
@@ -45,11 +48,10 @@ export function Landing() {
45
48
  </div>
46
49
  </div>
47
50
 
48
- {/* The figures are the roster the data view draws, read from the same
49
- module, so the panel is the app at work. `helix-stat` sets the
50
- number on the display face at a size the type scale does not
51
- reach. */}
52
- <helix-card class="specimen" separation="outlined">
51
+ {/* **The library at work, on the first screen.** The figures are the
52
+ roster the data view draws, read from the same module, so the panel
53
+ is the app itself, on glass over the light. */}
54
+ <helix-card class="specimen" material="glass" separation="outlined">
53
55
  <helix-text as="h2" slot="header" variant="title">
54
56
  The roster, in three figures
55
57
  </helix-text>
@@ -77,100 +79,51 @@ export function Landing() {
77
79
  <helix-text as="h2" variant="subheading">
78
80
  What you have
79
81
  </helix-text>
80
- {/* Three paragraphs about one installed thing, so they take a rule each
81
- and no box. `app.css` says why at more length. */}
82
- <div class="facts">
83
- <article class="fact">
84
- <helix-text as="h3" variant="title">
85
- Elements, not wrappers
86
- </helix-text>
87
- <helix-text as="p" emphasis="muted" variant="body">
88
- They are custom elements, so you write the tags and there is no per-component import
89
- to keep in step. One line in <helix-code>src/main.tsx</helix-code> registers all of
90
- them, and a subpath like <helix-code>@fusion.dev/helix/tabs</helix-code> registers
91
- one.
92
- </helix-text>
93
- <a data-link href={DOCS.elements}>
94
- Using the elements
95
- </a>
96
- </article>
97
-
98
- <article class="fact">
99
- <helix-text as="h3" variant="title">
100
- One set of tokens
101
- </helix-text>
102
- <helix-text as="p" emphasis="muted" variant="body">
103
- Every color is written once as a light and dark pair, so the control in the bar moves
104
- the whole page by setting a single attribute on the root. Type, spacing, radii and
105
- control sizes come from the same place.
106
- </helix-text>
107
- <a data-link href={DOCS.tokens}>
108
- Tokens
109
- </a>
110
- </article>
111
-
112
- <article class="fact">
113
- <helix-text as="h3" variant="title">
114
- A short stylesheet
115
- </helix-text>
116
- <helix-text as="p" emphasis="muted" variant="body">
117
- <helix-code>src/app.css</helix-code> holds this page's measure, the rhythm between its
118
- blocks, and nothing a component already draws. Where a component leaves a decision
119
- open it names a part: the data view reaches one to paint the row you tick.
120
- </helix-text>
121
- <a data-link href={DOCS.parts}>
122
- Overriding a component
123
- </a>
124
- </article>
125
- </div>
126
- </section>
127
-
128
- <section class="section">
129
- <helix-text as="h2" variant="subheading">
130
- Where to go next
131
- </helix-text>
132
- {/* **The whole card is the link, which is what `data-card` is for.** The
133
- base layer draws the ring, moves the card's border to the brand on
134
- hover, and leaves focus alone. Nothing inside may be interactive,
135
- since a link inside a link is neither valid nor reachable. */}
136
- <helix-grid columns={2} gap="md">
137
- <a data-card href="#/overview">
82
+ {/* **Each tile is a link, which is what `data-card` is for.** The base
83
+ layer draws the ring, moves the card's border to the brand on hover,
84
+ and leaves focus alone. Nothing inside may be interactive, since a
85
+ link inside a link is neither valid nor reachable. */}
86
+ <div class="features">
87
+ <a class="feature" data-card href={DOCS.elements}>
138
88
  <helix-card separation="outlined">
139
- {/* The route beside the name, on one baseline in the header. */}
140
- <helix-flex align-items="baseline" gap="sm" justify-content="between" slot="header">
141
- <helix-text as="h3" variant="title">
142
- The data view
143
- </helix-text>
144
- <helix-text emphasis="subtle" variant="code">
145
- /overview
146
- </helix-text>
147
- </helix-flex>
89
+ <span class="feature-mark">
90
+ <helix-icon name="cube" />
91
+ </span>
92
+ <helix-text as="h3" variant="title">
93
+ Custom elements
94
+ </helix-text>
148
95
  <helix-text as="p" emphasis="muted" variant="body">
149
- Twelve people from a local module, sorted, paged and selected with nothing wired up.
150
- The columns are markup you can read and the rows are one property, which is what
151
- keeps the same component working at ten thousand.
96
+ One import in <helix-code>src/main.tsx</helix-code> registers every tag.
152
97
  </helix-text>
153
98
  </helix-card>
154
99
  </a>
155
-
156
- <a data-card href="#/join">
100
+ <a class="feature" data-card href={DOCS.tokens}>
157
101
  <helix-card separation="outlined">
158
- <helix-flex align-items="baseline" gap="sm" justify-content="between" slot="header">
159
- <helix-text as="h3" variant="title">
160
- The form
161
- </helix-text>
162
- <helix-text emphasis="subtle" variant="code">
163
- /join
164
- </helix-text>
165
- </helix-flex>
102
+ <span class="feature-mark">
103
+ <helix-icon name="palette" />
104
+ </span>
105
+ <helix-text as="h3" variant="title">
106
+ One set of tokens
107
+ </helix-text>
166
108
  <helix-text as="p" emphasis="muted" variant="body">
167
- Five controls a <helix-code>&lt;form&gt;</helix-code> reads with{' '}
168
- <helix-code>FormData</helix-code>, because every one of them is a real form
169
- participant. The email field's complaint is the browser's own.
109
+ Every color, size, and space, in light and dark.
170
110
  </helix-text>
171
111
  </helix-card>
172
112
  </a>
173
- </helix-grid>
113
+ <a class="feature" data-card href={DOCS.parts}>
114
+ <helix-card separation="outlined">
115
+ <span class="feature-mark">
116
+ <helix-icon name="sliders-horizontal" />
117
+ </span>
118
+ <helix-text as="h3" variant="title">
119
+ Parts to style
120
+ </helix-text>
121
+ <helix-text as="p" emphasis="muted" variant="body">
122
+ Reach inside a component with <helix-code>::part()</helix-code>.
123
+ </helix-text>
124
+ </helix-card>
125
+ </a>
126
+ </div>
174
127
  </section>
175
128
  </div>
176
129
  )
@@ -65,8 +65,8 @@ export function Overview() {
65
65
 
66
66
  {/* A footnote to the table, so it takes the section's gap. */}
67
67
  <helix-text as="p" emphasis="muted" variant="caption">
68
- Filtering, column reordering, resizing, virtualized rows and a server mode that asks you
69
- for a page are all on{' '}
68
+ Filtering, column reordering, resizing, virtualized rows, and a server mode for large
69
+ results are on{' '}
70
70
  <a data-link href={DOCS.table}>
71
71
  the component's own page
72
72
  </a>
@@ -2,16 +2,16 @@ import { type Accessor, createSignal } from 'solid-js'
2
2
 
3
3
  /* **The whole router, which is a hash and a listener.**
4
4
 
5
- A starter should not pick your router for you, and three pages need
6
- `location.hash` and one event. Swap this file for Solid Router when you want
7
- nested routes or preloading: its `HashRouter` keeps these addresses.
5
+ Three pages need `location.hash` and one event, so the starter leaves the
6
+ router to you. Swap this file for Solid Router when you want nested routes or
7
+ preloading: its `HashRouter` keeps these addresses.
8
8
 
9
9
  A hash, because the History API wants a server that answers every path with
10
10
  the same document, and `vite preview` and wherever you deploy each have to be
11
- told to. A hash asks nothing of either. Each link in the app is a plain anchor
12
- to `#/` and a path. */
11
+ told to. A hash asks nothing of either. Each link in the app is a plain
12
+ anchor to `#/` and a path. */
13
13
 
14
- /** Where the reader is, as a path, so the first page is `/`. */
14
+ /** The current path, read from the hash, so the first page is `/`. */
15
15
  const read = (): string => window.location.hash.slice(1) || '/'
16
16
 
17
17
  const [path, setPath] = createSignal(read())
@@ -56,8 +56,8 @@ export function SignupForm() {
56
56
  <helix-input autocomplete="name" label="Name" name="name" required />
57
57
 
58
58
  {/* Validation is the platform's: `type` and `required` are set on the
59
- real input inside, and its own message shows once the reader has
60
- touched the field. Set `feedback` to say it in your own words. */}
59
+ real input inside, and its own message shows once the field has been
60
+ touched. Set `feedback` to say it in your own words. */}
61
61
  <helix-input
62
62
  hint="Where we send the welcome note."
63
63
  label="Email"
@@ -102,20 +102,20 @@ export function SignupForm() {
102
102
  and the component draws it with a tint and a bar on the inline
103
103
  start, so it survives being read in grayscale. */}
104
104
  <helix-callout tone="info">
105
- Nothing is posted anywhere. Submit it and the message shows exactly what a server would
106
- have been handed.
105
+ The form posts nothing. Submit it, and a message shows exactly what a server would
106
+ receive.
107
107
  </helix-callout>
108
108
  <helix-text as="h2" variant="title">
109
- What this is showing
109
+ What the form shows
110
110
  </helix-text>
111
111
  <helix-text as="p" emphasis="muted" variant="body">
112
- Every control is a form-associated custom element, so the submit reads them with{' '}
113
- <helix-code>new FormData(form)</helix-code> and nothing gathers the answers by hand.
114
- Reset the form and they all go back, the way an <helix-code>input</helix-code> does.
112
+ Every control is a form-associated custom element, so the submit reads them all
113
+ with <helix-code>new FormData(form)</helix-code>. Reset the form and they all go back,
114
+ the way an <helix-code>input</helix-code> does.
115
115
  </helix-text>
116
116
  <helix-text as="p" emphasis="muted" variant="body">
117
- Leave the email wrong and the complaint is the browser's own, in the reader's language.
118
- Handle is the controlled one: it refuses the change and writes back what it will accept.
117
+ Leave the email wrong and the browser shows its own message, in your language. Handle is
118
+ the controlled field: the page refuses each change and writes back a cleaned value.
119
119
  </helix-text>
120
120
  <a data-link href={DOCS.forms}>
121
121
  Forms
@@ -15,7 +15,7 @@ export function SiteFooter() {
15
15
  <footer class="site-footer">
16
16
  <div class="footer-row">
17
17
  <helix-text as="p" emphasis="subtle" variant="caption">
18
- Every component in here, with its API, its parts and its examples, has a page.
18
+ Every component here has a page, with its API, its parts, and its examples.
19
19
  </helix-text>
20
20
  <div class="footer-links">
21
21
  <a data-link="subtle" href={DOCS.gallery}>
@@ -13,8 +13,7 @@ const MARKS: Record<Mode, string> = { dark: 'moon', light: 'sun', system: 'monit
13
13
  * The bar across the top: the wordmark, the destinations, and the color mode.
14
14
  */
15
15
  export function SiteHeader() {
16
- /* `system` is the resting state, so the control draws the same glyph before
17
- and after the reader first touches it. */
16
+ /* `system` is the resting state, the mode the page follows until the control is pressed. */
18
17
  const [mode, setMode] = createSignal<Mode>('system')
19
18
 
20
19
  /**
@@ -26,7 +25,7 @@ export function SiteHeader() {
26
25
  * on a panel for a light preview inside a dark page.
27
26
  *
28
27
  * `system` removes the attribute. Writing out whichever mode is current would
29
- * freeze the page there the moment the reader's machine changed.
28
+ * hold the page there when the system's own setting changed.
30
29
  */
31
30
  const cycle = () => {
32
31
  const next = MODES[(MODES.indexOf(mode()) + 1) % MODES.length] ?? 'system'
@@ -4,8 +4,6 @@
4
4
  Delete it once you know your way around: nothing else imports it, and the
5
5
  route it answers becomes yours.
6
6
 
7
- **The heading says what this is, and the project's name stays in the bar.**
8
-
9
7
  **The calls to action are anchors.** A button that navigates is a link
10
8
  dressed as a button, and the two are different things to a keyboard and to
11
9
  a screen reader. The base stylesheet styles an anchor that asks with
@@ -23,13 +21,16 @@
23
21
 
24
22
  <div class="stack">
25
23
  <header class="first-screen">
24
+ <!-- **The light behind the first screen**: a helix, drawn by the library in
25
+ the theme's colors, so a new brand color relights it. It shows one still
26
+ frame where motion is reduced, and a gradient where the browser draws
27
+ without a GPU. -->
28
+ <helix-aura class="first-light" data-layer speed={0.4} terminus={0.8} variant="braid"></helix-aura>
26
29
  <div class="hero">
27
- <helix-text emphasis="muted" variant="label">Helix starter</helix-text>
28
- <helix-text as="h1">Every tag on this page is Helix</helix-text>
29
- <helix-text as="p" class="lede" emphasis="muted" variant="body">
30
- Nothing here is a wrapper: the tags are the library's own elements, and every color,
31
- size and space inside them comes from one set of tokens. Three routes are laid down, and
32
- all of them are yours.
30
+ <helix-tag emphasis="subtle" tone="primary">Starter</helix-tag>
31
+ <helix-text as="h1" variant="display">Helix design system</helix-text>
32
+ <helix-text as="p" class="lede" variant="body">
33
+ Web components in your brand's colors, drawn from one set of tokens.
33
34
  </helix-text>
34
35
  <div class="actions">
35
36
  <a data-button="solid" data-button-tone="primary" href="#/overview">See the data view</a>
@@ -37,10 +38,10 @@
37
38
  </div>
38
39
  </div>
39
40
 
40
- <!-- The figures are the roster the data view draws, read from the same
41
- module, so the panel is the app at work. `helix-stat` sets the number
42
- on the display face at a size the type scale does not reach. -->
43
- <helix-card class="specimen" separation="outlined">
41
+ <!-- **The library at work, on the first screen.** The figures are the roster
42
+ the data view draws, read from the same module, so the panel is the app
43
+ itself, on glass over the light. -->
44
+ <helix-card class="specimen" material="glass" separation="outlined">
44
45
  <helix-text as="h2" slot="header" variant="title">The roster, in three figures</helix-text>
45
46
  <helix-stat-group divided>
46
47
  <helix-stat>
@@ -62,76 +63,38 @@
62
63
 
63
64
  <section class="section">
64
65
  <helix-text as="h2" variant="subheading">What you have</helix-text>
65
- <!-- Three paragraphs about one installed thing, so they take a rule each
66
- and no box. `app.css` says why at more length. -->
67
- <div class="facts">
68
- <article class="fact">
69
- <helix-text as="h3" variant="title">Elements, not wrappers</helix-text>
70
- <helix-text as="p" emphasis="muted" variant="body">
71
- They are custom elements, so you write the tags and there is no per-component import
72
- to keep in step. One line in <helix-code>src/main.ts</helix-code> registers all of
73
- them, and a subpath like <helix-code>@fusion.dev/helix/tabs</helix-code> registers
74
- one.
75
- </helix-text>
76
- <a data-link href={DOCS.elements}>Using the elements</a>
77
- </article>
78
-
79
- <article class="fact">
80
- <helix-text as="h3" variant="title">One set of tokens</helix-text>
81
- <helix-text as="p" emphasis="muted" variant="body">
82
- Every color is written once as a light and dark pair, so the control in the bar moves
83
- the whole page by setting a single attribute on the root. Type, spacing, radii and
84
- control sizes come from the same place.
85
- </helix-text>
86
- <a data-link href={DOCS.tokens}>Tokens</a>
87
- </article>
88
-
89
- <article class="fact">
90
- <helix-text as="h3" variant="title">A short stylesheet</helix-text>
91
- <helix-text as="p" emphasis="muted" variant="body">
92
- <helix-code>src/app.css</helix-code> holds this page's measure, the rhythm between its
93
- blocks, and nothing a component already draws. Where a component leaves a decision
94
- open it names a part: the data view reaches one to paint the row you tick.
95
- </helix-text>
96
- <a data-link href={DOCS.parts}>Overriding a component</a>
97
- </article>
98
- </div>
99
- </section>
100
-
101
- <section class="section">
102
- <helix-text as="h2" variant="subheading">Where to go next</helix-text>
103
- <!-- **The whole card is the link, which is what `data-card` is for.** The
104
- base layer draws the ring, moves the card's border to the brand on
105
- hover, and leaves focus alone. Nothing inside may be interactive,
106
- since a link inside a link is neither valid nor reachable. -->
107
- <helix-grid columns={2} gap="md">
108
- <a data-card href="#/overview">
66
+ <!-- **Each tile is a link, which is what `data-card` is for.** The base layer
67
+ draws the ring, moves the card's border to the brand on hover, and leaves
68
+ focus alone. Nothing inside may be interactive, since a link inside a link
69
+ is neither valid nor reachable. -->
70
+ <div class="features">
71
+ <a class="feature" data-card href={DOCS.elements}>
109
72
  <helix-card separation="outlined">
110
- <helix-flex align-items="baseline" gap="sm" justify-content="between" slot="header">
111
- <helix-text as="h3" variant="title">The data view</helix-text>
112
- <helix-text emphasis="subtle" variant="code">/overview</helix-text>
113
- </helix-flex>
73
+ <span class="feature-mark"><helix-icon name="cube"></helix-icon></span>
74
+ <helix-text as="h3" variant="title">Custom elements</helix-text>
114
75
  <helix-text as="p" emphasis="muted" variant="body">
115
- Twelve people from a local module, sorted, paged and selected with nothing wired up.
116
- The columns are markup you can read and the rows are one property, which is what
117
- keeps the same component working at ten thousand.
76
+ One import in <helix-code>src/main.ts</helix-code> registers every tag.
118
77
  </helix-text>
119
78
  </helix-card>
120
79
  </a>
121
-
122
- <a data-card href="#/join">
80
+ <a class="feature" data-card href={DOCS.tokens}>
123
81
  <helix-card separation="outlined">
124
- <helix-flex align-items="baseline" gap="sm" justify-content="between" slot="header">
125
- <helix-text as="h3" variant="title">The form</helix-text>
126
- <helix-text emphasis="subtle" variant="code">/join</helix-text>
127
- </helix-flex>
82
+ <span class="feature-mark"><helix-icon name="palette"></helix-icon></span>
83
+ <helix-text as="h3" variant="title">One set of tokens</helix-text>
128
84
  <helix-text as="p" emphasis="muted" variant="body">
129
- Five controls a <helix-code>&lt;form&gt;</helix-code> reads with
130
- <helix-code>FormData</helix-code>, because every one of them is a real form
131
- participant. The email field's complaint is the browser's own.
85
+ Every color, size, and space, in light and dark.
132
86
  </helix-text>
133
87
  </helix-card>
134
88
  </a>
135
- </helix-grid>
89
+ <a class="feature" data-card href={DOCS.parts}>
90
+ <helix-card separation="outlined">
91
+ <span class="feature-mark"><helix-icon name="sliders-horizontal"></helix-icon></span>
92
+ <helix-text as="h3" variant="title">Parts to style</helix-text>
93
+ <helix-text as="p" emphasis="muted" variant="body">
94
+ Reach inside a component with <helix-code>::part()</helix-code>.
95
+ </helix-text>
96
+ </helix-card>
97
+ </a>
98
+ </div>
136
99
  </section>
137
100
  </div>
@@ -59,8 +59,8 @@
59
59
 
60
60
  <!-- A footnote to the table, so it takes the section's gap. -->
61
61
  <helix-text as="p" emphasis="muted" variant="caption">
62
- Filtering, column reordering, resizing, virtualized rows and a server mode that asks you
63
- for a page are all on
62
+ Filtering, column reordering, resizing, virtualized rows, and a server mode for large results
63
+ are on
64
64
  <a data-link href={DOCS.table}>the component's own page</a>.
65
65
  </helix-text>
66
66
  </section>
@@ -70,8 +70,8 @@
70
70
  <helix-input autocomplete="name" label="Name" name="name" required></helix-input>
71
71
 
72
72
  <!-- Validation is the platform's: `type` and `required` are set on the
73
- real input inside, and its own message shows once the reader has
74
- touched the field. Set `feedback` to say it in your own words. -->
73
+ real input inside, and its own message shows once the field has been
74
+ touched. Set `feedback` to say it in your own words. -->
75
75
  <helix-input
76
76
  hint="Where we send the welcome note."
77
77
  label="Email"
@@ -109,18 +109,17 @@
109
109
  and the component draws it with a tint and a bar on the inline
110
110
  start, so it survives being read in grayscale. -->
111
111
  <helix-callout tone="info">
112
- Nothing is posted anywhere. Submit it and the message shows exactly what a server would
113
- have been handed.
112
+ The form posts nothing. Submit it, and a message shows exactly what a server would receive.
114
113
  </helix-callout>
115
- <helix-text as="h2" variant="title">What this is showing</helix-text>
114
+ <helix-text as="h2" variant="title">What the form shows</helix-text>
116
115
  <helix-text as="p" emphasis="muted" variant="body">
117
- Every control is a form-associated custom element, so the submit reads them with
118
- <helix-code>new FormData(form)</helix-code> and nothing gathers the answers by hand.
119
- Reset the form and they all go back, the way an <helix-code>input</helix-code> does.
116
+ Every control is a form-associated custom element, so the submit reads them all with
117
+ <helix-code>new FormData(form)</helix-code>. Reset the form and they all go back,
118
+ the way an <helix-code>input</helix-code> does.
120
119
  </helix-text>
121
120
  <helix-text as="p" emphasis="muted" variant="body">
122
- Leave the email wrong and the complaint is the browser's own, in the reader's language.
123
- Handle is the controlled one: it refuses the change and writes back what it will accept.
121
+ Leave the email wrong and the browser shows its own message, in your language. Handle is the
122
+ controlled field: the page refuses each change and writes back a cleaned value.
124
123
  </helix-text>
125
124
  <a data-link href={DOCS.forms}>Forms</a>
126
125
  </aside>
@@ -15,7 +15,7 @@
15
15
  <footer class="site-footer">
16
16
  <div class="footer-row">
17
17
  <helix-text as="p" emphasis="subtle" variant="caption">
18
- Every component in here, with its API, its parts and its examples, has a page.
18
+ Every component here has a page, with its API, its parts, and its examples.
19
19
  </helix-text>
20
20
  <div class="footer-links">
21
21
  <a data-link="subtle" href={DOCS.gallery}>Components</a>
@@ -10,8 +10,7 @@
10
10
  /** The glyph each mode is announced and drawn with. */
11
11
  const MARKS: Record<Mode, string> = { dark: 'moon', light: 'sun', system: 'monitor' }
12
12
 
13
- /* `system` is the resting state, so the control draws the same glyph before
14
- and after the reader first touches it. */
13
+ /* `system` is the resting state, the mode the page follows until the control is pressed. */
15
14
  let mode = $state<Mode>('system')
16
15
 
17
16
  /**
@@ -23,7 +22,7 @@
23
22
  * on a panel for a light preview inside a dark page.
24
23
  *
25
24
  * `system` removes the attribute. Writing out whichever mode is current would
26
- * freeze the page there the moment the reader's machine changed.
25
+ * hold the page there when the system's own setting changed.
27
26
  */
28
27
  const cycle = () => {
29
28
  const next = MODES[(MODES.indexOf(mode) + 1) % MODES.length] ?? 'system'