@fusion.dev/helix-docs 0.142.1 → 0.144.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.
@@ -19,10 +19,11 @@ accessible only when you also handle your parts.
19
19
  Every component implements the keyboard pattern for its role. You do not write
20
20
  any of it:
21
21
 
22
- - Arrow keys move within \`Tabs\`, \`Listbox\`, and \`Menu\`.
22
+ - Arrow keys move within \`Tabs\`, \`Listbox\`, \`Menu\`, \`Select\`, \`Combobox\`, and
23
+ the days of a date picker.
23
24
  - \`Escape\` closes an overlay.
24
25
  - \`Home\` and \`End\` go to the first and last item.
25
- - Typing jumps to a matching item.
26
+ - In \`Listbox\`, \`Select\`, \`Menu\`, and \`Tree\`, typing jumps to a matching item.
26
27
 
27
28
  ### Focus
28
29
 
@@ -66,6 +67,13 @@ words are yours to choose. An icon-only control has no other text to name it:
66
67
  ></helix-icon-button>
67
68
  \`\`\`
68
69
 
70
+ A button or a form control that renders with no name warns once in the console:
71
+ \`<helix-icon-button> has no accessible name\`, followed by the ways to give it
72
+ one. The check runs a moment after the control first renders, so a label your
73
+ framework writes beside the control in the same pass counts. The warning has the
74
+ kind \`missing-name\`, so \`@fusion.dev/helix-diagnostics\` counts it with the
75
+ other runtime events.
76
+
69
77
  ### \`label\` and \`aria-label\`
70
78
 
71
79
  \`label\` renders visible text and names the control through that text.
@@ -107,11 +115,24 @@ and is read where it sits. Neither component is a variant of the other.
107
115
 
108
116
  \`aria-labelledby\` and \`aria-describedby\` inside a shadow root cannot point to an
109
117
  id in your document. The browser drops the reference silently and reports no
110
- error. For this reason, every control renders its own label, and connecting two
111
- components by id does not work. See [Forms and validation](./forms).
118
+ error. For this reason, every control renders its own label. See
119
+ [Forms and validation](./forms).
120
+
121
+ **What you write on the host reaches the control inside it.** The form controls,
122
+ \`Button\`, and \`IconButton\` carry these down to the element a screen reader is on:
123
+
124
+ - \`aria-labelledby\` and \`aria-describedby\`, as element references, so the ids
125
+ you name in your document resolve.
126
+ - A \`<label for>\` that points at the host, or a \`<label>\` around it, when the
127
+ control has no \`label\` of its own.
128
+ - \`aria-expanded\`, \`aria-haspopup\`, \`aria-controls\`, \`aria-invalid\`, and
129
+ \`aria-pressed\`.
130
+ - \`aria-label\` on \`Button\`, \`IconButton\`, and \`Switch\`. A field renders its
131
+ \`aria-label\` as a hidden label.
112
132
 
113
- A \`<label for>\` in your markup cannot reach into a shadow root either, so it
114
- does not name a Helix control. Use the control's own \`label\`.
133
+ A \`<label>\` around a control also reads the words inside the control, such as
134
+ the names of its buttons. Use \`<label for>\` or the control's own \`label\` to name
135
+ it with your words alone.
115
136
 
116
137
  When a relationship has to cross the boundary, the components use
117
138
  \`ElementInternals\` and element-reference properties. They are the only mechanism
@@ -335,8 +356,8 @@ customElements.define('acme-combobox', AcmeCombobox)
335
356
  \`\`\`
336
357
 
337
358
  That one line sets the prefix. The styled tier sets its prefix the same way, with
338
- \`static override tier = 'helix-'\` and nothing else. The static appears 116 times
339
- in the headless manifest, so you can find it there.
359
+ \`static override tier = 'helix-'\` and nothing else. Every element in the
360
+ headless manifest carries the static, so you can find it there.
340
361
 
341
362
  ## Register every component a component renders
342
363
 
@@ -349,12 +370,13 @@ open.
349
370
 
350
371
  [//]: # (renders)
351
372
 
352
- **27 of the 98 headless families interpolate another family's tag**, across 20 distinct children.
373
+ **28 of the 98 headless families interpolate another family's tag**, across 20 distinct children.
353
374
 
354
375
  | Family | Renders |
355
376
  |---|---|
356
377
  | \`area-chart\`, \`bar-chart\`, \`copy-button\`, \`donut-chart\`, \`heatmap\`, \`line-chart\`, \`scatter-chart\` | \`tooltip\` |
357
378
  | \`chat\` | \`chat-message\` |
379
+ | \`checkbox-group\` | \`checkbox\` |
358
380
  | \`code-block\`, \`object-inspector\` | \`copy-button\` |
359
381
  | \`color-input\` | \`color-picker\` |
360
382
  | \`color-picker\` | \`button\`, \`button-group\`, \`slider\` |
@@ -404,24 +426,26 @@ Use \`visibility\` so the page does not reflow when the definitions arrive.
404
426
 
405
427
  ### Typings for your tags
406
428
 
407
- \`@fusion.dev/helix-cem\` is the generator we use for our own typings. It reads
408
- your package and writes \`jsx.d.ts\`, \`vue.d.ts\`, and \`svelte.d.ts\` for your tags,
409
- with every member your subclasses inherit from ours. Add a \`cem.config.ts\`
410
- beside your \`package.json\`:
429
+ Your typings come from a manifest of your package. \`helix manifest build\`, in
430
+ \`@fusion.dev/helix-cli\`, writes one that includes every member your subclasses
431
+ inherit from ours. Name each Helix package you extend and where its manifest is:
411
432
 
412
- \`\`\`ts
413
- import type { HelixCemOptions } from '@fusion.dev/helix-cem'
414
-
415
- export default {
416
- frameworkTypes: true,
417
- packageName: 'acme-system',
418
- tier: 'styled',
419
- } satisfies HelixCemOptions
433
+ \`\`\`sh
434
+ helix manifest build . --tier styled \\
435
+ --dependency @fusion.dev/helix=node_modules/@fusion.dev/helix/custom-elements.json \\
436
+ --dependency @fusion.dev/helix-headless=node_modules/@fusion.dev/helix-headless/custom-elements.json \\
437
+ --dependency @fusion.dev/helix-core=node_modules/@fusion.dev/helix-core/custom-elements.json \\
438
+ > custom-elements.json
420
439
  \`\`\`
421
440
 
422
- Then run \`bun --bun helix-cem\`. It finds the classes you extend through your
423
- \`dependencies\`. The typings for \`acme-combobox\` then include the hundred or so
424
- members it inherits, as well as the two you wrote.
441
+ Then run a typings generator over it. Our own typings start from
442
+ \`@wc-toolkit/jsx-types\` and \`@wc-toolkit/vuejs-types\`. The typings for
443
+ \`acme-combobox\` then include the hundred or so members it inherits, as well as
444
+ the two you wrote.
445
+
446
+ \`@fusion.dev/helix-cem\`, the step that runs those generators for our packages
447
+ and corrects what they write, is not published. It is build tooling for this
448
+ repository.
425
449
 
426
450
  ### The tag map
427
451
 
@@ -576,6 +600,32 @@ table should not be seen, hide it visually, and the data is still there:
576
600
  The table's caption becomes the chart's accessible name unless you set \`label\`.
577
601
  The caption usually has the right words already.
578
602
 
603
+ Each chart writes a short summary for screen readers, which starts with that
604
+ name. The drawing is hidden from screen readers, and the summary gives the one
605
+ reading a chart is usually read for:
606
+
607
+ - \`Bar Chart\`: each series' highest reading.
608
+ - \`Line Chart\`: each series' latest reading.
609
+ - \`Area Chart\`: the latest total and each part's share of it.
610
+ - \`Donut Chart\`: each slice's share of the whole.
611
+ - \`Scatter Chart\`: each series' number of points and how strongly the two
612
+ measures relate.
613
+
614
+ \`Heatmap\` is an image with that name. \`Sparkline\` takes a \`label\` of its own.
615
+
616
+ ## Tables that change
617
+
618
+ A chart follows its table. It redraws when you edit a cell, add a row, or
619
+ replace the table with a new one under the same id. It also draws a table that
620
+ arrives after the chart does, such as one a framework renders once its data
621
+ loads.
622
+
623
+ A blank cell, or one that does not hold a number, is a gap in its series. The
624
+ row keeps its place on the axis, a line breaks at the gap, a bar chart draws no
625
+ bar there, and a heatmap draws the cell with no tone. The readings after the gap
626
+ stay under their own labels, and the tooltip for that row still shows the
627
+ row's cells.
628
+
579
629
  ## Series colors
580
630
 
581
631
  Helix has twenty-four series color tokens, in order, from
@@ -804,8 +854,8 @@ title: Color
804
854
 
805
855
  # Color
806
856
 
807
- Seventy-four of the library's 185 tokens are colors, and they make up most of a
808
- theme. Each color token is named for its role. No token is named for how it
857
+ Colors are the largest group of the library's tokens, and they make up most of
858
+ a theme. Each color token is named for its role. No token is named for how it
809
859
  looks, because a name like \`--brand-blue-500\` becomes wrong as soon as you change
810
860
  the theme.
811
861
 
@@ -1066,11 +1116,18 @@ for a slot of the same name. Helix never renders both.
1066
1116
 
1067
1117
  \`\`\`html
1068
1118
  <!-- The property -->
1069
- <helix-tooltip content="Save"></helix-tooltip>
1119
+ <helix-tooltip
1120
+ content="Save"
1121
+ for="save"
1122
+ id="save-tip"
1123
+ ></helix-tooltip>
1070
1124
 
1071
1125
  <!-- The slot, which replaces it -->
1072
- <helix-tooltip>
1073
- <strong>Save</strong>, or press <helix-kbd>⌘S</helix-kbd>
1126
+ <helix-tooltip
1127
+ for="save"
1128
+ id="save-tip"
1129
+ >
1130
+ <span slot="content"><strong>Save</strong>, or press <helix-kbd>⌘S</helix-kbd></span>
1074
1131
  </helix-tooltip>
1075
1132
  \`\`\`
1076
1133
 
@@ -1084,8 +1141,9 @@ examples put the closing tag on the same line as the opening tag.
1084
1141
 
1085
1142
  ## Set a button's width with the layout
1086
1143
 
1087
- A button has no \`width\` or \`fill\` property, for the same reason it has no \`size\`
1088
- property. How wide a control is depends on the region it is in.
1144
+ A button has no \`fill\` property and no \`size\` property. How wide a control is
1145
+ depends on the region it is in. \`width="full"\` fills the row a button sits in,
1146
+ and the layout decides everything else.
1089
1147
 
1090
1148
  A button already stretches in a column flex or a grid, because a stretch-aligned
1091
1149
  parent stretches its children:
@@ -1163,8 +1221,8 @@ and then a second attribute to hide it is the same as having no visible label.
1163
1221
 
1164
1222
  \`Option\`, \`Listbox\`, and \`Select\` are three families so that the keyboard
1165
1223
  handling, the filtering, the multi-select rules, and the active-item tracking
1166
- are written once. \`Select\` renders a \`Listbox\` internally. A future combobox
1167
- will too, and so would a command palette.
1224
+ are written once. \`Select\` renders a \`Listbox\` internally, and so does \`Combobox\`. A command
1225
+ palette would too.
1168
1226
 
1169
1227
  For the same reason, we wrote \`DrilldownController\`. Since it was first written,
1170
1228
  \`Menu\` had held a page stack and derived its rows, and none of that code
@@ -1376,6 +1434,10 @@ against a dispatch, so every event you can listen for is documented.
1376
1434
  | \`helix-before-change\` | A value is about to change, cancelable |
1377
1435
  | \`helix-before-toggle\` | A checked state is about to flip, cancelable |
1378
1436
  | \`helix-before-open\`, \`helix-before-close\` | An open state is about to change, cancelable |
1437
+ | \`helix-before-activate\`, \`helix-activate\` | A set is about to make a different child current, cancelable, and then did |
1438
+ | \`helix-before-pin\`, \`helix-pin\` | A chat transcript is about to be pinned to the bottom or let go of it, cancelable, and then was |
1439
+ | \`helix-before-resize\`, \`helix-resized\` | A splitter's divider is about to settle, cancelable, and then did |
1440
+ | \`helix-before-collapse\`, \`helix-collapse\` | A splitter's pane is about to shut or reopen, cancelable, and then did |
1379
1441
  | \`helix-select\` | An item was chosen from a set |
1380
1442
  | \`helix-dismiss\` | A user asked for something to close |
1381
1443
  | \`helix-next\`, \`helix-previous\` | Movement through a sequence |
@@ -1392,12 +1454,36 @@ Every stateful component also sends native events once the change is applied:
1392
1454
 
1393
1455
  - \`input\` and \`change\` on a value control
1394
1456
  - \`toggle\` on anything that opens, carrying \`newState\` and \`oldState\` as
1395
- \`<details>\` does
1457
+ \`<details>\` does. It is a \`ToggleEvent\` in browsers that have one, and it is
1458
+ sent whether the change came from a reader or from assigning \`open\`
1396
1459
  - \`close\` on a dialog
1397
1460
  - \`load\` and \`error\` on an image
1398
1461
 
1399
1462
  Each component's page lists the events it dispatches, with the class and the
1400
- detail.
1463
+ detail. The table above lists the common ones.
1464
+
1465
+ ## Requests under a plain name
1466
+
1467
+ A few events with no \`before\` in their name are also cancelable requests. Each
1468
+ is sent before the change, and you refuse the change with \`preventDefault()\`:
1469
+
1470
+ - \`helix-navigate\` on Pagination, Data Table, and Date Picker
1471
+ - \`helix-sort\`, \`helix-filter\`, \`helix-select\`, and \`helix-reorder\` on Data Table
1472
+ - \`helix-select\` on Carousel
1473
+
1474
+ Each of these requests had its name before the library had a word for the
1475
+ notification, so the notification has its own name. It is sent after the
1476
+ change, is not cancelable, and carries the new state:
1477
+
1478
+ - \`helix-activate\` after the page moves on Pagination and Data Table, and after
1479
+ the slide moves on Carousel
1480
+ - \`helix-sorted\`, \`helix-filtered\`, \`helix-selected\`, and \`helix-reordered\` on
1481
+ Data Table
1482
+ - \`input\` and \`change\` together on Pagination Size, as a native \`<select>\`
1483
+ sends them
1484
+
1485
+ A request that is refused sends no notification. Date Picker's \`helix-navigate\`
1486
+ moves the month on show, and the month sends no notification.
1401
1487
 
1402
1488
  ## Events in a framework
1403
1489
 
@@ -1510,23 +1596,62 @@ participants:
1510
1596
  ></helix-input>
1511
1597
  \`\`\`
1512
1598
 
1513
- Submitting an empty form is blocked, and the browser points to the control.
1514
- \`checkValidity()\`, \`reportValidity()\`, and \`:invalid\` work as they do for native
1515
- controls.
1599
+ Submitting an empty form is blocked, and the browser moves focus to the control
1600
+ and shows its message there. Each control has the validity API of a native
1601
+ control:
1602
+
1603
+ - \`checkValidity()\` and \`reportValidity()\`
1604
+ - \`setCustomValidity(message)\`
1605
+ - \`validity\`, \`validationMessage\`, and \`willValidate\`
1516
1606
 
1517
- \`feedback\` replaces the browser's message. When \`feedback\` is empty, the
1518
- browser shows its own message, which is localized and familiar. When you set it,
1519
- the control shows the message in the words your product uses:
1607
+ \`:invalid\` matches the control as it matches a native one.
1608
+
1609
+ \`value-missing-message\` replaces the browser's message for a required control
1610
+ that is empty. When it is not set, the browser shows its own message, which is
1611
+ localized and familiar:
1520
1612
 
1521
1613
  \`\`\`html
1522
1614
  <helix-input
1523
- feedback="We need this to send your receipt."
1524
1615
  label="Email"
1525
1616
  name="email"
1526
1617
  required
1618
+ value-missing-message="We need this to send your receipt."
1527
1619
  ></helix-input>
1528
1620
  \`\`\`
1529
1621
 
1622
+ **\`feedback\` says what is wrong, and the form does not submit while it is
1623
+ set.** Use it for a verdict the browser cannot reach, such as one your server
1624
+ returned. The control shows the message under itself and is invalid until you
1625
+ clear \`feedback\`:
1626
+
1627
+ \`\`\`html
1628
+ <helix-input
1629
+ feedback="That name is taken."
1630
+ label="Username"
1631
+ name="username"
1632
+ ></helix-input>
1633
+ \`\`\`
1634
+
1635
+ \`setCustomValidity()\` blocks the form in the same way, and the control shows
1636
+ its message once the reader has edited the field.
1637
+
1638
+ ## Focus and Enter
1639
+
1640
+ \`focus()\` on a control moves focus to the element a reader would reach with
1641
+ Tab, and pressing a \`<label>\` that names the control does the same. In a group,
1642
+ that is the chosen radio, or the first one when nothing is chosen.
1643
+
1644
+ Pressing Enter in a single-line field submits its form, as Enter in a native
1645
+ text field does. These fields do it:
1646
+
1647
+ - \`Input\`, \`NumberInput\`, and \`PinInput\`
1648
+ - \`DateInput\`, \`TimeInput\`, and \`ColorInput\`
1649
+ - \`Combobox\`, while its list is closed
1650
+
1651
+ The form's first submit button is pressed, and a \`helix-button type="submit"\`
1652
+ counts as one, for a native field too. A form with no submit button is
1653
+ submitted when it has only one text field.
1654
+
1530
1655
  \`Radio.Group\` and \`Toggle.Group\` take part in the form for their members. Each
1531
1656
  group owns the \`name\`, the \`value\`, and the validity. A single radio is an
1532
1657
  answer, and the group is the control it answers. \`Checkbox.Group\` works the
@@ -1620,7 +1745,7 @@ Add the frame, with an element inside it for the renderer to draw in:
1620
1745
  Give the frame its notes and links, make the renderer, and connect the two:
1621
1746
 
1622
1747
  \`\`\`js
1623
- import '@fusion.dev/helix'
1748
+ import '@fusion.dev/helix/graph'
1624
1749
  import { connectGraph } from '@fusion.dev/helix-graph'
1625
1750
  import { sigmaDriver } from '@fusion.dev/helix-graph/sigma'
1626
1751
  import Graph from 'graphology'
@@ -1775,7 +1900,10 @@ is a button that shows or hides the group's notes, in the drawing and in the
1775
1900
  list:
1776
1901
 
1777
1902
  \`\`\`html
1778
- <helix-graph label="Company notes" legend>
1903
+ <helix-graph
1904
+ label="Company notes"
1905
+ legend
1906
+ >
1779
1907
  <div></div>
1780
1908
  </helix-graph>
1781
1909
  \`\`\`
@@ -1823,7 +1951,10 @@ and the frame brings it into view with its neighbors. Start with one selected
1823
1951
  with \`default-active\`:
1824
1952
 
1825
1953
  \`\`\`html
1826
- <helix-graph default-active="roadmap" label="Research notes">
1954
+ <helix-graph
1955
+ default-active="roadmap"
1956
+ label="Research notes"
1957
+ >
1827
1958
  <div></div>
1828
1959
  </helix-graph>
1829
1960
  \`\`\`
@@ -1835,7 +1966,11 @@ Set \`depth\` to show only the notes within that many links of the selected one,
1835
1966
  for a graph too large to read at once:
1836
1967
 
1837
1968
  \`\`\`html
1838
- <helix-graph default-active="roadmap" depth="2" label="Research notes">
1969
+ <helix-graph
1970
+ default-active="roadmap"
1971
+ depth="2"
1972
+ label="Research notes"
1973
+ >
1839
1974
  <div></div>
1840
1975
  </helix-graph>
1841
1976
  \`\`\`
@@ -1908,7 +2043,10 @@ finger moves it. A graph embedded in a page takes the wheel from a reader who
1908
2043
  is scrolling past it. Set \`gestures\` on the frame to share them:
1909
2044
 
1910
2045
  \`\`\`html
1911
- <helix-graph gestures="cooperative" label="Research notes">
2046
+ <helix-graph
2047
+ gestures="cooperative"
2048
+ label="Research notes"
2049
+ >
1912
2050
  <div></div>
1913
2051
  </helix-graph>
1914
2052
  \`\`\`
@@ -1929,7 +2067,11 @@ drawing takes all of it, as at the top of a page. A Notes button among the
1929
2067
  controls opens them over the drawing:
1930
2068
 
1931
2069
  \`\`\`html
1932
- <helix-graph gestures="cooperative" label="Research notes" no-panel>
2070
+ <helix-graph
2071
+ gestures="cooperative"
2072
+ label="Research notes"
2073
+ no-panel
2074
+ >
1933
2075
  <div></div>
1934
2076
  </helix-graph>
1935
2077
  \`\`\`
@@ -1998,7 +2140,8 @@ leaves removing it to your framework.
1998
2140
  minus keys zoom it. Set \`controls="pan zoom fullscreen"\` to add buttons that
1999
2141
  move it.
2000
2142
  - The list is a listbox, named by \`notes-label\`. Arrow keys, Home, End, Page
2001
- Up, and Page Down move through it, and Enter or Space selects a note.
2143
+ Up, and Page Down move through it, typing a letter moves to the next note
2144
+ whose name starts with it, and Enter or Space selects a note.
2002
2145
  - In the search field, Down moves into the list, and Escape empties the search.
2003
2146
  With \`no-panel\`, Escape on an empty search closes the list.
2004
2147
  - Screen readers read the selected note first, then how each other note links
@@ -2254,15 +2397,15 @@ Each file has its own export. If you bring your own reset or your own ramp,
2254
2397
  import the two files you want and skip \`helix.css\`.
2255
2398
 
2256
2399
  - **\`primitives.css\`** holds the raw ramp that the semantic layer is derived
2257
- from. The seven \`--helix-seed-*\` properties are read here. Your own code
2258
- should not name a primitive, and leaving the file out does not enforce that.
2259
- \`tokens.css\` refers to a primitive 297 times, so without \`primitives.css\`
2260
- every semantic token resolves to nothing. We measured a page without it:
2400
+ from. The \`--helix-seed-*\` properties are read here. Your own code should
2401
+ not name a primitive, and leaving the file out does not enforce that.
2402
+ \`tokens.css\` refers to the primitives throughout, so without
2403
+ \`primitives.css\` every semantic token resolves to nothing. We measured a page without it:
2261
2404
  \`--helix-color-background\` computes to \`rgba(0, 0, 0, 0)\`, and so does every
2262
2405
  other color. [Theming](theming.mdx) also depends on this file, because without
2263
2406
  it, setting \`--helix-seed-brand\` changes nothing.
2264
- - **\`tokens.css\`** declares the semantic layer: 185 custom properties in 15
2265
- categories, plus \`color-scheme: light dark\` on \`:root\`. The files below read
2407
+ - **\`tokens.css\`** declares the semantic layer, the custom properties grouped
2408
+ by category, plus \`color-scheme: light dark\` on \`:root\`. The files below read
2266
2409
  from it, and it reads from \`primitives.css\`.
2267
2410
  - **\`base.css\`** holds the element reset, the type scale on bare \`h1\` through
2268
2411
  \`h6\`, and the recipes for markup that Helix does not render. It reads tokens.
@@ -2277,25 +2420,23 @@ components. The order then stays visible in one place.
2277
2420
 
2278
2421
  ## Register the elements
2279
2422
 
2280
- \`\`\`ts
2281
- import '@fusion.dev/helix'
2282
- \`\`\`
2283
-
2284
- This import has a side effect: it calls \`customElements.define\` once for every
2285
- element. You can run it more than once. A second \`define\` for the same tag
2286
- throws an error and stops the rest of the module, so the helper behind the
2287
- import checks the registry first.
2288
-
2289
- To register only some elements, import them from subpaths:
2423
+ Import each family you use from its subpath:
2290
2424
 
2291
2425
  \`\`\`ts
2292
2426
  import '@fusion.dev/helix/button'
2293
2427
  import '@fusion.dev/helix/dialog'
2294
2428
  \`\`\`
2295
2429
 
2296
- Import from subpaths when you use a few components. The package has side
2297
- effects by design, so a bundler keeps everything you import. The whole-package
2298
- import registers every element, and a subpath registers only its family.
2430
+ Each import has a side effect: it calls \`customElements.define\` for the
2431
+ elements of that family, and for the families they render. You can run it more
2432
+ than once. A second \`define\` for the same tag throws an error and stops the rest
2433
+ of the module, so the helper behind the import checks the registry first.
2434
+
2435
+ The package has side effects by design, so a bundler keeps everything you
2436
+ import. \`import '@fusion.dev/helix'\` registers every element in the library,
2437
+ which is the whole library in your bundle. Use it for a prototype, and use
2438
+ subpaths in an app. [Metrics](./metrics) lists the size of each family and of
2439
+ the whole package.
2299
2440
 
2300
2441
  ## Check the installation
2301
2442
 
@@ -2502,12 +2643,12 @@ reason.
2502
2643
  bun add @fusion.dev/helix @fusion.dev/helix-styles
2503
2644
  \`\`\`
2504
2645
 
2505
- Add two imports at your app root, in this order. Then you can use the elements
2506
- anywhere:
2646
+ Import the stylesheet at your app root, then each family you use. Then you can
2647
+ use those elements anywhere:
2507
2648
 
2508
2649
  \`\`\`ts
2509
2650
  import '@fusion.dev/helix-styles/helix.css'
2510
- import '@fusion.dev/helix'
2651
+ import '@fusion.dev/helix/accordion'
2511
2652
  \`\`\`
2512
2653
 
2513
2654
  \`\`\`html
@@ -2635,8 +2776,8 @@ Six families format numbers or dates and take a \`locale\`:
2635
2776
 
2636
2777
  | | |
2637
2778
  |---|---|
2638
- | \`Date Input\`, \`Date Picker\` | Date formats and first day of week |
2639
- | \`Time Input\`, \`Time Picker\` | 12 or 24 hour, and separators |
2779
+ | \`Date Input\`, \`Date Picker\` | Date formats, and the first day of the week where \`first-day-of-week\` is not set |
2780
+ | \`Time Input\`, \`Time Picker\` | 12 or 24 hour, separators, and the AM and PM on the wheels |
2640
2781
  | \`Pagination\` | Grouped thousands in page numbers |
2641
2782
  | \`File Input\` | File sizes |
2642
2783
 
@@ -2651,6 +2792,15 @@ If you do not set \`locale\`, these controls use the browser's locale, which is
2651
2792
  usually correct. Set \`locale\` when your users choose your application's
2652
2793
  language separately from the language of their operating system.
2653
2794
 
2795
+ The first day of the week comes from \`Intl.Locale\`'s week information, which
2796
+ Firefox does not provide. There, and where you set no \`locale\`, the week starts
2797
+ on Sunday. Set \`first-day-of-week\` to choose the day yourself.
2798
+
2799
+ \`locale\` formats dates, times, and numbers. It does not translate the words a
2800
+ control speaks, such as "Previous month" on a calendar or "Hour" on a time
2801
+ wheel. Set those through their properties, such as \`previous-label\` and
2802
+ \`next-label\` on Date Picker and Date Input, and \`hour-label\` on Time Picker.
2803
+
2654
2804
  Formatting uses \`Intl\`, so Helix bundles no locale data, and you have nothing to
2655
2805
  keep up to date.
2656
2806
 
@@ -2680,8 +2830,13 @@ it reports:
2680
2830
  - \`bad-input-message\`
2681
2831
  - \`range-underflow-message\`
2682
2832
  - \`range-overflow-message\`
2833
+ - \`step-mismatch-message\`
2683
2834
  - \`too-short-message\`
2684
2835
 
2836
+ Date Picker, Date Input, Time Picker, and Time Input also take
2837
+ \`unavailable-message\`, for a date or time that \`disable-dates\`, \`disable-days\`,
2838
+ or \`disable-times\` rules out.
2839
+
2685
2840
  A message appears in the browser's own validation bubble and on the line under
2686
2841
  the field. \`feedback\` does not reach the bubble. If you do not set a message, a
2687
2842
  text field shows the browser's own message, which is already in your user's
@@ -2695,6 +2850,18 @@ language. Every other control shows its English sentence.
2695
2850
  ></helix-number-input>
2696
2851
  \`\`\`
2697
2852
 
2853
+ Color Picker and Color Input say a color's name to a screen reader, such as
2854
+ "vibrant red". Set \`color-words\` to a JSON table of the words a name is made
2855
+ of. The keys are the English words, and they match the strings that React
2856
+ Aria's \`@react-stately/color\` translates, so you can reuse that table.
2857
+
2858
+ \`\`\`html
2859
+ <helix-color-picker
2860
+ color-words='{"red": "rot", "vibrant": "kräftiges", "colorName": "{lightness} {chroma} {hue}"}'
2861
+ lang="de"
2862
+ ></helix-color-picker>
2863
+ \`\`\`
2864
+
2698
2865
  **Pass these strings from your own translation system.** Helix ships English
2699
2866
  defaults and no translation tools. If Helix had its own string catalog, you
2700
2867
  would have to keep two catalogs in step.
@@ -2774,7 +2941,7 @@ Add the map frame, an element for MapLibre to draw in, and your places:
2774
2941
  Create the map with a style from your theme, then connect it to the frame:
2775
2942
 
2776
2943
  \`\`\`js
2777
- import '@fusion.dev/helix'
2944
+ import '@fusion.dev/helix/map'
2778
2945
  import 'maplibre-gl/dist/maplibre-gl.css'
2779
2946
  import { colorsReady, connectMap } from '@fusion.dev/helix-map'
2780
2947
  import { followTheme, mapLibreDriver, mapLibreStyle } from '@fusion.dev/helix-map/maplibre'
@@ -2899,7 +3066,11 @@ is the map's. Give the container a position, such as \`position: relative\`:
2899
3066
 
2900
3067
  \`\`\`html
2901
3068
  <section class="hero">
2902
- <helix-map fill credit-placement="bottom-end" label="Downtown Austin">
3069
+ <helix-map
3070
+ credit-placement="bottom-end"
3071
+ fill
3072
+ label="Downtown Austin"
3073
+ >
2903
3074
  <div id="map"></div>
2904
3075
  </helix-map>
2905
3076
  <div class="hero-words">
@@ -2973,7 +3144,10 @@ A map embedded in a page, such as a hero, takes the wheel from a reader who is
2973
3144
  scrolling past it. Set \`gestures\` on the frame to share them:
2974
3145
 
2975
3146
  \`\`\`html
2976
- <helix-map gestures="cooperative" label="Downtown Austin">
3147
+ <helix-map
3148
+ gestures="cooperative"
3149
+ label="Downtown Austin"
3150
+ >
2977
3151
  <div id="map"></div>
2978
3152
  </helix-map>
2979
3153
  \`\`\`
@@ -3225,7 +3399,10 @@ is a map type, which the frame's \`map-type\` attribute chooses:
3225
3399
  - \`satellite\`: the imagery alone, without the roads and names.
3226
3400
 
3227
3401
  With \`layers\` in the frame's \`controls\`, the layers menu opens with a card for
3228
- each map type, showing a picture of the map in it. Set \`max-zoom\` to the deepest
3402
+ each map type, showing a picture of the map in it. Choosing a card sends
3403
+ \`helix-before-change\` with the type's name, \`standard\`, \`hybrid\`, or
3404
+ \`satellite\`, and \`change\` once \`map-type\` holds it. Cancel the first to keep the
3405
+ current type, or listen for the second to store the choice. Set \`max-zoom\` to the deepest
3229
3406
  zoom your provider has tiles for, and the map enlarges those tiles when a user
3230
3407
  zooms in further.
3231
3408
 
@@ -3298,6 +3475,10 @@ tile is lit while its layer is shown. Pressing a tile sets its layer's \`hidden\
3298
3475
  attribute, and \`connectMap\` does not draw a hidden layer. Write \`hidden\` on a
3299
3476
  layer to start it turned off.
3300
3477
 
3478
+ Before it sets \`hidden\`, a tile sends \`helix-before-toggle\` from the layer, with
3479
+ \`checked\` true when the layer is to be shown. Store the choice from it, or
3480
+ cancel it to keep the layer as it is.
3481
+
3301
3482
  Give layers the same \`group\` to show them as one tile, such as a route and the
3302
3483
  dotted legs at its ends. The tile takes the name of the first layer in the
3303
3484
  group, and shows or hides every layer in it. Keep labels short, such as
@@ -3405,7 +3586,7 @@ on its own.
3405
3586
 
3406
3587
  | | Raw | Gzip | Brotli |
3407
3588
  |---|---|---|---|
3408
- | Lit and \`@fusion.dev/helix-core\` | 186,211 | 59,377 | 50,257 |
3589
+ | Lit and \`@fusion.dev/helix-core\` | 182,087 | 57,026 | 49,129 |
3409
3590
 
3410
3591
  ## Whole packages
3411
3592
 
@@ -3416,12 +3597,12 @@ either barrel. The per-component tables show what your page pays.
3416
3597
 
3417
3598
  | Package | Raw | Gzip | Brotli | |
3418
3599
  |---|---|---|---|---|
3419
- | \`@fusion.dev/helix-core\` | 185,764 | 59,007 | 50,046 | The element base class, mixins, decorators, and floating positioning. |
3420
- | \`@fusion.dev/helix-headless\` | 749,093 | 194,398 | 150,798 | Every headless family. The barrel entry includes all of them. |
3421
- | \`@fusion.dev/helix-icons\` | 55,565 | 17,727 | 14,864 | The whole glyph set. |
3600
+ | \`@fusion.dev/helix-core\` | 181,641 | 56,641 | 48,897 | The element base class, mixins, decorators, and floating positioning. |
3601
+ | \`@fusion.dev/helix-headless\` | 929,891 | 247,016 | 188,830 | Every headless family. The barrel entry includes all of them. |
3602
+ | \`@fusion.dev/helix-icons\` | 55,738 | 17,784 | 15,143 | The whole glyph set. |
3422
3603
  | \`@fusion.dev/helix-theme\` | 3,626 | 1,597 | 1,384 | The JavaScript that runs the derivation engine. Most sites run it at build time, and a theme switcher runs it in the browser. |
3423
3604
  | \`fusion_helix_theme_bg.wasm\` | 490,270 | 155,600 | 125,779 | The derivation engine itself, in WebAssembly. The entry above loads it when the engine runs. |
3424
- | \`@fusion.dev/helix\` | 1,296,493 | 303,276 | 221,718 | Every styled family. |
3605
+ | \`@fusion.dev/helix\` | 1,471,844 | 349,349 | 250,882 | Every styled family. |
3425
3606
  | \`lit\` | 15,394 | 6,118 | 5,460 | Lit itself, listed so you can subtract it from every row above. |
3426
3607
 
3427
3608
  ## Stylesheets
@@ -3435,68 +3616,70 @@ shows the whole cost of using the base layer on its own.
3435
3616
  | File | Raw | Gzip | Brotli | |
3436
3617
  |---|---|---|---|---|
3437
3618
  | \`base.css\` | 30,786 | 4,465 | 3,884 | The base layer. It styles markup Helix does not render, and it works with no JavaScript. |
3438
- | \`elements.css\` | 8,807 | 1,488 | 1,318 | Hides each element until its definition loads. It is generated from the tags in \`@fusion.dev/helix\`. |
3619
+ | \`elements.css\` | 8,862 | 1,492 | 1,318 | Hides each element until its definition loads. It is generated from the tags in \`@fusion.dev/helix\`. |
3439
3620
  | \`helix.css\` | 207 | 148 | 118 | The other four stylesheets in one import, in the order they must load. |
3440
3621
  | \`primitives.css\` | 7,510 | 1,402 | 1,201 | The primitive layer. It is private, and it ships because \`tokens.css\` refers to it. |
3441
3622
  | \`tokens.css\` | 22,349 | 2,664 | 2,247 | The 193 semantic tokens. Every styled component needs them. |
3442
3623
 
3443
3624
  ## What the numbers say
3444
3625
 
3445
- **Most of your first component is the shared runtime.** The median styled family is 21,977 bytes gzipped alone, and it adds 2,263 to a page that already has Helix. The shared runtime is 90 percent of the first component, and the component itself is 10 percent. Ten typical components cost the first number once, plus nine of the added number. The two columns in the tables below let you work that out for your own components.
3626
+ **Most of your first component is the shared runtime.** The median styled family is 17,001 bytes gzipped alone, and it adds 2,926 to a page that already has Helix. The shared runtime is 83 percent of the first component, and the component itself is 17 percent. Ten typical components cost the first number once, plus nine of the added number. The two columns in the tables below let you work that out for your own components.
3446
3627
 
3447
- Across the 104 styled components, the smallest is \`code\` at 10,492 bytes gzipped alone, and the largest is \`data-table\` at 64,440. Every family together is 303,276.
3628
+ Across the 104 styled components, the smallest is \`code\` at 10,676 bytes gzipped alone, and the largest is \`data-table\` at 56,196. Every family together is 349,349.
3448
3629
 
3449
- No family imports a barrel. The \`barrels\` rule in \`fusion workspace\` enforces that. \`@fusion.dev/helix-headless\` marks every module in \`dist\` as having side effects, which is true of a file that calls \`customElements.define\`. A bundler can remove none of it. One \`import { HelixHeadlessButton } from '@fusion.dev/helix-headless'\` costs 194,398 bytes gzipped, whatever else the page imports. That is 9 times the median family above. All 104 styled families import the headless family they extend directly. The rule checks the shape of the import, so it applies to any package that sets \`sideEffects\`, whatever its name.
3630
+ No family imports a barrel. The \`barrels\` rule in \`fusion workspace\` enforces that. \`@fusion.dev/helix-headless\` marks every module in \`dist\` as having side effects, which is true of a file that calls \`customElements.define\`. A bundler can remove none of it. One \`import { HelixHeadlessButton } from '@fusion.dev/helix-headless'\` costs 247,016 bytes gzipped, whatever else the page imports. That is 15 times the median family above. All 104 styled families import the headless family they extend directly. The rule checks the shape of the import, so it applies to any package that sets \`sideEffects\`, whatever its name.
3450
3631
 
3451
- The headless tier never had the problem, so it serves as the control. \`@fusion.dev/helix-core\` is \`sideEffects: false\`, and the median headless family is 22,536 bytes gzipped alone.
3632
+ The headless tier never had the problem, so it serves as the control. \`@fusion.dev/helix-core\` is \`sideEffects: false\`, and the median headless family is 16,148 bytes gzipped alone.
3452
3633
 
3453
3634
  ## Compared with other systems
3454
3635
 
3455
- We compare Helix with four other libraries of custom elements. \`turbo run peers\` measured them on 2026-08-24. It installs pinned versions into \`.local\` and bundles them with the same harness as the tables above. The Helix rows are measured on every run of \`bun run gen:metrics\`, so they always match this repository.
3636
+ We compare Helix with the libraries of custom elements listed under the table. \`turbo run peers\` measured them on 2026-08-24. It installs pinned versions into \`.local\` and bundles them with the same harness as the tables above. The Helix rows are measured on every run of \`bun run gen:metrics\`, so they always match this repository.
3456
3637
 
3457
3638
  Every system in the table is built on Lit. The runtime is the same library in every column, so the differences come from the components. React component libraries are left out, because comparing a custom element with a React component would measure the framework.
3458
3639
 
3459
- The table has no whole-library row. That row would compare how many components each vendor ships and how each vendor counts a component. It would look like a measurement and mean little. The table compares five components that every system has.
3640
+ The table has no whole-library row. That row would compare how many components each vendor ships and how each vendor counts a component. It would look like a measurement and mean little. The table compares components that most systems ship, and a system without one says so.
3460
3641
 
3461
3642
  | Component | System | Raw | Gzip | Brotli |
3462
3643
  |---|---|---|---|---|
3463
- | \`button\` | **Helix** | 45,627 | 13,160 | 11,597 |
3644
+ | \`button\` | **Helix** | 56,398 | 16,247 | 14,165 |
3464
3645
  | | Carbon | 133,058 | 20,959 | 17,685 |
3465
3646
  | | Material Web | 47,060 | 14,173 | 12,591 |
3466
3647
  | | Shoelace | 62,628 | 18,287 | 15,805 |
3467
3648
  | | Spectrum | 98,792 | 22,045 | 18,674 |
3468
- | \`checkbox\` | **Helix** | 50,794 | 14,480 | 12,734 |
3649
+ | \`checkbox\` | **Helix** | 60,002 | 16,960 | 14,858 |
3469
3650
  | | Carbon | 60,255 | 15,609 | 13,550 |
3470
3651
  | | Material Web | 43,785 | 13,556 | 12,015 |
3471
3652
  | | Shoelace | 47,614 | 15,177 | 13,301 |
3472
3653
  | | Spectrum | 62,492 | 15,437 | 13,481 |
3473
- | \`dialog\` | **Helix** | 42,582 | 12,668 | 11,151 |
3654
+ | \`dialog\` | **Helix** | 54,741 | 16,320 | 14,276 |
3474
3655
  | | Carbon | 510,866 | 67,390 | 39,189 |
3475
3656
  | | Material Web | 34,238 | 11,510 | 10,229 |
3476
3657
  | | Shoelace | 52,754 | 17,698 | 15,554 |
3477
3658
  | | Spectrum | 155,708 | 31,899 | 26,262 |
3478
- | \`radio\` | **Helix** | 54,213 | 14,925 | 13,136 |
3659
+ | \`radio\` | **Helix** | 64,144 | 17,850 | 15,648 |
3479
3660
  | | Carbon | 63,055 | 16,887 | 14,605 |
3480
3661
  | | Material Web | 41,044 | 13,234 | 11,757 |
3481
3662
  | | Shoelace | 34,865 | 12,027 | 10,559 |
3482
3663
  | | Spectrum | 38,685 | 10,660 | 9,370 |
3483
- | \`switch\` | **Helix** | 47,784 | 13,981 | 12,292 |
3664
+ | \`switch\` | **Helix** | 57,461 | 16,577 | 14,545 |
3484
3665
  | | Carbon | 69,423 | 17,127 | 14,764 |
3485
3666
  | | Material Web | 50,155 | 14,577 | 12,935 |
3486
3667
  | | Shoelace | 37,833 | 11,814 | 10,568 |
3487
3668
  | | Spectrum | 62,322 | 15,059 | 13,321 |
3488
- | \`tabs\` | **Helix** | 48,895 | 14,049 | 12,334 |
3669
+ | \`tabs\` | **Helix** | 55,917 | 16,074 | 14,020 |
3489
3670
  | | Carbon | 578,766 | 73,537 | 43,235 |
3490
3671
  | | Material Web | 38,883 | 12,820 | 11,368 |
3491
3672
  | | Shoelace | 54,573 | 17,140 | 15,068 |
3492
3673
  | | Spectrum | 64,875 | 18,298 | 16,283 |
3493
- | \`tooltip\` | **Helix** | 69,601 | 22,599 | 19,950 |
3674
+ | \`tooltip\` | **Helix** | 74,148 | 23,682 | 20,846 |
3494
3675
  | | Carbon | 189,382 | 30,354 | 22,273 |
3495
3676
  | | Material Web | | not shipped | |
3496
3677
  | | Shoelace | 57,412 | 20,220 | 17,933 |
3497
3678
  | | Spectrum | 136,599 | 40,552 | 35,286 |
3498
3679
 
3499
- At least one system is smaller than Helix on \`checkbox\`, \`dialog\`, \`radio\`, \`switch\`, \`tabs\`, \`tooltip\`. The largest gap is radio against Spectrum, at 4,265 bytes gzipped. 8 of 28 peer measurements are smaller than the Helix row.
3680
+ At least one system is smaller than Helix on \`button\`, \`checkbox\`, \`dialog\`, \`radio\`, \`switch\`, \`tabs\`, \`tooltip\`. The largest gap is radio against Spectrum, at 7,190 bytes gzipped. 15 of 27 peer measurements are smaller than the Helix row.
3681
+
3682
+ Helix's \`radio\` family includes Radio Group, so its row carries an element that some peer rows measure without.
3500
3683
 
3501
3684
  - **Carbon** \`@carbon/web-components@2.61.0\`. Its dialog is Modal, its radio is Radio Button, and its switch is Toggle.
3502
3685
  - **Material Web** \`@material/web@2.5.0\`. Ships no tooltip. Its button is measured as the filled one, there being no single button element.
@@ -3540,104 +3723,104 @@ Structure, accessibility, state, and form participation. It has no presentation
3540
3723
 
3541
3724
  | Family | Alone raw | Alone gzip | Alone brotli | Added raw | Added gzip | Added brotli |
3542
3725
  |---|---|---|---|---|---|---|
3543
- | \`accordion\` | 94,146 | 30,683 | 25,054 | 2,875 | 725 | 591 |
3544
- | \`announcement\` | 91,561 | 29,855 | 24,344 | 1,386 | 365 | 315 |
3545
- | \`app-header\` | 35,147 | 10,774 | 9,482 | 1,248 | 261 | 267 |
3546
- | \`area-chart\` | 81,239 | 26,784 | 23,616 | 11,166 | 3,382 | 2,736 |
3547
- | \`avatar\` | 37,234 | 11,388 | 10,035 | 3,296 | 894 | 740 |
3548
- | \`badge\` | 34,683 | 10,703 | 9,380 | 1,163 | 301 | 227 |
3549
- | \`bar-chart\` | 82,848 | 27,158 | 23,952 | 12,769 | 3,695 | 3,195 |
3550
- | \`blockquote\` | 34,697 | 10,730 | 9,428 | 774 | 177 | 163 |
3551
- | \`breadcrumbs\` | 90,601 | 29,203 | 23,965 | 1,965 | 444 | 405 |
3552
- | \`button\` | 39,369 | 11,986 | 10,530 | 3,195 | 817 | 682 |
3553
- | \`button-group\` | 34,553 | 10,610 | 9,316 | 661 | 141 | 91 |
3554
- | \`callout\` | 89,781 | 29,091 | 23,899 | 975 | 274 | 278 |
3555
- | \`canvas\` | 95,827 | 28,300 | 24,815 | 50,036 | 14,960 | 12,555 |
3556
- | \`card\` | 34,587 | 10,627 | 9,339 | 694 | 140 | 89 |
3557
- | \`carousel\` | 100,004 | 32,186 | 26,392 | 10,943 | 2,734 | 2,326 |
3558
- | \`chat\` | 113,488 | 37,075 | 30,397 | 17,449 | 5,101 | 4,303 |
3559
- | \`checkbox\` | 44,186 | 13,038 | 11,447 | 2,821 | 784 | 591 |
3560
- | \`checkbox-group\` | 47,310 | 13,724 | 12,070 | 5,425 | 1,366 | 1,117 |
3561
- | \`code\` | 33,172 | 10,193 | 8,966 | 451 | 78 | 40 |
3562
- | \`code-block\` | 135,605 | 44,216 | 37,288 | 17,443 | 4,511 | 3,880 |
3563
- | \`color-input\` | 153,586 | 48,220 | 40,723 | 25,853 | 6,032 | 5,036 |
3564
- | \`color-picker\` | 119,956 | 37,674 | 30,975 | 19,676 | 4,708 | 3,949 |
3565
- | \`combobox\` | 148,369 | 46,880 | 39,435 | 21,175 | 5,214 | 4,226 |
3566
- | \`command\` | 118,287 | 36,946 | 30,260 | 18,064 | 4,594 | 3,744 |
3567
- | \`copy-button\` | 130,185 | 42,566 | 35,820 | 12,019 | 2,957 | 2,432 |
3568
- | \`data-table\` | 188,875 | 57,528 | 48,563 | 57,535 | 14,589 | 12,192 |
3569
- | \`date-input\` | 146,628 | 46,372 | 38,994 | 19,212 | 4,832 | 4,047 |
3570
- | \`date-picker\` | 101,780 | 32,896 | 26,931 | 9,900 | 2,706 | 2,203 |
3571
- | \`description-list\` | 34,656 | 10,565 | 9,269 | 1,132 | 172 | 155 |
3572
- | \`dialog\` | 38,205 | 11,660 | 10,266 | 2,717 | 777 | 650 |
3573
- | \`divider\` | 34,903 | 10,810 | 9,498 | 981 | 255 | 196 |
3574
- | \`donut-chart\` | 78,982 | 25,782 | 22,727 | 10,339 | 2,970 | 2,540 |
3575
- | \`drawer\` | 36,958 | 11,299 | 9,931 | 1,761 | 470 | 398 |
3576
- | \`drilldown\` | 98,646 | 32,043 | 26,104 | 5,704 | 1,493 | 1,176 |
3577
- | \`empty\` | 35,150 | 10,853 | 9,531 | 956 | 243 | 163 |
3578
- | \`file-input\` | 102,144 | 32,877 | 26,856 | 6,266 | 1,808 | 1,396 |
3579
- | \`filter-input\` | 158,975 | 49,595 | 41,937 | 28,070 | 6,799 | 5,629 |
3580
- | \`format-date\` | 38,166 | 11,770 | 10,393 | 2,868 | 694 | 582 |
3581
- | \`graph\` | 116,500 | 37,045 | 30,487 | 11,480 | 3,231 | 2,788 |
3582
- | \`heatmap\` | 80,204 | 25,983 | 22,886 | 10,997 | 2,991 | 2,539 |
3583
- | \`icon\` | 89,288 | 28,883 | 23,689 | 1,018 | 246 | 208 |
3584
- | \`icon-button\` | 39,768 | 12,019 | 10,552 | 3,594 | 858 | 630 |
3585
- | \`image\` | 36,726 | 11,157 | 9,803 | 3,157 | 812 | 638 |
3586
- | \`input\` | 101,182 | 32,362 | 26,507 | 4,746 | 1,276 | 977 |
3587
- | \`kbd\` | 36,507 | 11,395 | 10,035 | 2,976 | 915 | 738 |
3588
- | \`legend\` | 38,559 | 11,901 | 10,461 | 1,080 | 277 | 260 |
3589
- | \`lightbox\` | 42,999 | 12,950 | 11,347 | 4,807 | 1,236 | 1,042 |
3590
- | \`line-chart\` | 80,779 | 26,487 | 23,389 | 10,792 | 3,086 | 2,597 |
3591
- | \`list\` | 35,609 | 10,806 | 9,494 | 1,726 | 333 | 276 |
3592
- | \`listbox\` | 109,996 | 35,061 | 28,605 | 11,263 | 3,065 | 2,451 |
3593
- | \`loader\` | 34,793 | 10,731 | 9,434 | 900 | 231 | 145 |
3594
- | \`map\` | 135,023 | 40,242 | 33,379 | 33,030 | 7,708 | 6,231 |
3595
- | \`megamenu\` | 65,092 | 21,481 | 18,897 | 4,941 | 1,278 | 1,033 |
3596
- | \`menu\` | 128,815 | 42,454 | 35,618 | 8,856 | 2,188 | 1,829 |
3597
- | \`meter\` | 37,983 | 11,583 | 10,180 | 4,100 | 1,064 | 940 |
3598
- | \`navigation\` | 36,542 | 11,280 | 9,892 | 1,417 | 341 | 301 |
3599
- | \`notifications\` | 105,825 | 33,645 | 27,464 | 11,384 | 2,617 | 2,170 |
3600
- | \`number-input\` | 104,106 | 33,173 | 27,093 | 7,671 | 1,991 | 1,556 |
3601
- | \`object-inspector\` | 143,395 | 46,771 | 39,449 | 19,705 | 5,249 | 4,382 |
3602
- | \`option\` | 36,848 | 11,172 | 9,859 | 2,959 | 666 | 414 |
3603
- | \`outline\` | 39,911 | 12,458 | 10,978 | 4,628 | 1,326 | 1,080 |
3604
- | \`pagination\` | 152,465 | 47,582 | 40,030 | 27,823 | 6,528 | 5,329 |
3605
- | \`pin-input\` | 46,366 | 13,784 | 12,137 | 5,242 | 1,563 | 1,171 |
3606
- | \`popover\` | 62,296 | 20,725 | 18,214 | 1,899 | 513 | 488 |
3607
- | \`progress\` | 35,834 | 11,003 | 9,678 | 1,951 | 490 | 464 |
3608
- | \`qr-code\` | 46,483 | 15,044 | 13,242 | 12,984 | 4,828 | 4,059 |
3609
- | \`quote\` | 34,076 | 10,491 | 9,221 | 552 | 119 | 67 |
3610
- | \`radio\` | 45,916 | 13,428 | 11,812 | 2,874 | 726 | 578 |
3611
- | \`rating\` | 48,121 | 14,398 | 12,675 | 6,689 | 1,880 | 1,538 |
3612
- | \`scatter-chart\` | 80,683 | 26,413 | 23,275 | 11,471 | 3,371 | 2,830 |
3613
- | \`scroll-area\` | 36,319 | 11,164 | 9,809 | 2,743 | 736 | 655 |
3614
- | \`select\` | 140,575 | 45,037 | 37,796 | 16,146 | 4,083 | 3,351 |
3615
- | \`skeleton\` | 33,265 | 10,227 | 8,965 | 544 | 106 | 45 |
3616
- | \`skip-link\` | 34,855 | 10,796 | 9,475 | 1,178 | 334 | 243 |
3617
- | \`slider\` | 46,905 | 13,806 | 12,176 | 5,628 | 1,517 | 1,238 |
3618
- | \`sparkline\` | 40,978 | 12,925 | 11,386 | 2,387 | 794 | 744 |
3619
- | \`speed-dial\` | 120,323 | 40,071 | 33,736 | 3,743 | 918 | 690 |
3620
- | \`splitter\` | 44,358 | 13,240 | 11,678 | 10,283 | 2,587 | 2,196 |
3621
- | \`stat\` | 35,041 | 10,666 | 9,363 | 1,148 | 185 | 79 |
3622
- | \`steps\` | 98,861 | 31,677 | 25,901 | 6,295 | 1,470 | 1,224 |
3623
- | \`switch\` | 43,417 | 12,921 | 11,362 | 1,650 | 514 | 364 |
3624
- | \`table\` | 100,971 | 32,855 | 26,742 | 10,159 | 2,795 | 2,312 |
3625
- | \`tabs\` | 42,654 | 12,774 | 11,190 | 3,925 | 822 | 664 |
3626
- | \`tag\` | 90,014 | 29,133 | 23,798 | 908 | 198 | 207 |
3627
- | \`textarea\` | 45,604 | 13,423 | 11,778 | 3,997 | 1,063 | 806 |
3628
- | \`time-input\` | 159,758 | 49,619 | 41,795 | 29,051 | 7,093 | 5,869 |
3629
- | \`time-picker\` | 118,842 | 37,643 | 30,852 | 19,136 | 5,108 | 4,201 |
3630
- | \`timeline\` | 90,450 | 29,131 | 23,931 | 1,809 | 362 | 265 |
3631
- | \`toast\` | 93,807 | 30,268 | 24,715 | 4,078 | 949 | 780 |
3632
- | \`toggle\` | 47,603 | 13,959 | 12,288 | 3,342 | 815 | 573 |
3633
- | \`toolbar\` | 36,647 | 11,354 | 9,978 | 2,624 | 704 | 576 |
3634
- | \`tooltip\` | 66,523 | 21,821 | 19,323 | 6,494 | 1,749 | 1,431 |
3635
- | \`tour\` | 72,280 | 23,251 | 20,408 | 11,097 | 2,772 | 2,303 |
3636
- | \`tree\` | 100,665 | 32,488 | 26,473 | 7,224 | 1,878 | 1,567 |
3637
- | \`trend\` | 89,328 | 28,928 | 23,780 | 1,056 | 268 | 266 |
3638
- | \`video\` | 157,146 | 49,284 | 41,734 | 32,577 | 7,665 | 6,638 |
3639
- | \`video-playlist\` | 136,305 | 44,054 | 36,962 | 14,942 | 3,424 | 2,916 |
3640
- | \`virtual-list\` | 40,597 | 12,666 | 11,132 | 2,413 | 719 | 592 |
3726
+ | \`accordion\` | 44,701 | 13,626 | 11,933 | 4,240 | 1,216 | 879 |
3727
+ | \`announcement\` | 40,721 | 12,427 | 10,877 | 1,422 | 470 | 220 |
3728
+ | \`app-header\` | 37,314 | 11,161 | 9,828 | 1,800 | 610 | 304 |
3729
+ | \`area-chart\` | 90,369 | 29,258 | 25,668 | 13,495 | 4,140 | 3,231 |
3730
+ | \`avatar\` | 40,474 | 12,079 | 10,630 | 4,317 | 1,319 | 916 |
3731
+ | \`badge\` | 36,128 | 10,891 | 9,562 | 1,149 | 436 | 150 |
3732
+ | \`bar-chart\` | 92,950 | 29,977 | 26,287 | 15,690 | 4,734 | 3,684 |
3733
+ | \`blockquote\` | 36,294 | 10,964 | 9,606 | 912 | 368 | 166 |
3734
+ | \`breadcrumbs\` | 38,511 | 11,586 | 10,180 | 2,248 | 662 | 420 |
3735
+ | \`button\` | 49,106 | 14,753 | 12,864 | 4,710 | 1,442 | 966 |
3736
+ | \`button-group\` | 36,012 | 10,792 | 9,472 | 661 | 278 | 17 |
3737
+ | \`callout\` | 41,362 | 12,662 | 11,077 | 1,329 | 509 | 341 |
3738
+ | \`canvas\` | 97,945 | 28,734 | 25,129 | 50,699 | 15,269 | 12,665 |
3739
+ | \`card\` | 37,123 | 11,127 | 9,754 | 1,604 | 507 | 199 |
3740
+ | \`carousel\` | 49,032 | 14,602 | 12,873 | 12,343 | 3,380 | 2,522 |
3741
+ | \`chat\` | 63,883 | 19,478 | 17,158 | 18,377 | 5,465 | 4,344 |
3742
+ | \`checkbox\` | 53,376 | 15,507 | 13,630 | 2,958 | 958 | 510 |
3743
+ | \`checkbox-group\` | 58,828 | 16,890 | 14,812 | 7,836 | 2,158 | 1,422 |
3744
+ | \`code\` | 34,631 | 10,379 | 9,095 | 451 | 217 | 5 |
3745
+ | \`code-block\` | 97,970 | 30,627 | 26,843 | 23,818 | 6,378 | 5,060 |
3746
+ | \`color-input\` | 126,667 | 38,020 | 33,193 | 37,761 | 9,575 | 7,587 |
3747
+ | \`color-picker\` | 89,459 | 26,331 | 23,074 | 30,390 | 8,129 | 6,339 |
3748
+ | \`combobox\` | 124,918 | 36,824 | 32,129 | 35,736 | 8,855 | 6,997 |
3749
+ | \`command\` | 86,526 | 24,600 | 21,456 | 26,825 | 7,073 | 5,455 |
3750
+ | \`copy-button\` | 91,383 | 28,739 | 25,185 | 17,224 | 4,559 | 3,426 |
3751
+ | \`data-table\` | 166,647 | 48,062 | 41,467 | 76,823 | 19,901 | 15,778 |
3752
+ | \`date-input\` | 135,874 | 39,621 | 34,569 | 34,269 | 8,259 | 6,505 |
3753
+ | \`date-picker\` | 62,134 | 18,124 | 16,067 | 16,799 | 4,429 | 3,354 |
3754
+ | \`description-list\` | 36,115 | 10,751 | 9,429 | 1,132 | 329 | 52 |
3755
+ | \`dialog\` | 49,122 | 15,045 | 13,119 | 4,950 | 1,588 | 1,070 |
3756
+ | \`divider\` | 36,362 | 10,991 | 9,663 | 981 | 387 | 140 |
3757
+ | \`donut-chart\` | 88,589 | 28,406 | 24,960 | 13,145 | 3,946 | 3,122 |
3758
+ | \`drawer\` | 49,857 | 15,264 | 13,305 | 4,473 | 1,494 | 972 |
3759
+ | \`drilldown\` | 52,271 | 15,920 | 13,912 | 6,372 | 1,788 | 1,225 |
3760
+ | \`empty\` | 36,800 | 11,098 | 9,726 | 956 | 375 | 156 |
3761
+ | \`file-input\` | 70,157 | 21,089 | 18,462 | 13,699 | 4,113 | 3,073 |
3762
+ | \`filter-input\` | 122,233 | 36,317 | 31,769 | 32,194 | 8,036 | 6,293 |
3763
+ | \`format-date\` | 41,800 | 12,579 | 11,116 | 4,302 | 1,231 | 822 |
3764
+ | \`graph\` | 68,878 | 20,642 | 18,131 | 14,811 | 4,762 | 3,746 |
3765
+ | \`heatmap\` | 93,526 | 29,776 | 26,031 | 13,605 | 3,880 | 2,960 |
3766
+ | \`icon\` | 93,519 | 29,356 | 25,023 | 55,716 | 19,410 | 15,184 |
3767
+ | \`icon-button\` | 49,502 | 14,787 | 12,881 | 5,109 | 1,488 | 931 |
3768
+ | \`image\` | 39,391 | 11,664 | 10,247 | 3,695 | 1,088 | 699 |
3769
+ | \`input\` | 58,901 | 17,599 | 15,313 | 7,196 | 2,442 | 1,597 |
3770
+ | \`kbd\` | 39,704 | 12,134 | 10,658 | 3,432 | 1,172 | 699 |
3771
+ | \`legend\` | 42,474 | 12,907 | 11,291 | 2,304 | 797 | 399 |
3772
+ | \`lightbox\` | 52,296 | 15,432 | 13,574 | 7,865 | 2,197 | 1,462 |
3773
+ | \`line-chart\` | 90,719 | 29,240 | 25,692 | 13,695 | 4,083 | 3,203 |
3774
+ | \`list\` | 37,108 | 10,989 | 9,641 | 1,766 | 503 | 212 |
3775
+ | \`listbox\` | 72,278 | 21,086 | 18,482 | 16,468 | 4,603 | 3,470 |
3776
+ | \`loader\` | 38,134 | 11,443 | 10,061 | 1,966 | 701 | 428 |
3777
+ | \`map\` | 88,866 | 24,638 | 21,318 | 37,993 | 9,921 | 7,589 |
3778
+ | \`megamenu\` | 67,545 | 21,979 | 19,301 | 5,166 | 1,504 | 950 |
3779
+ | \`menu\` | 84,482 | 27,139 | 23,697 | 10,758 | 2,901 | 2,034 |
3780
+ | \`meter\` | 39,935 | 11,963 | 10,523 | 4,407 | 1,321 | 936 |
3781
+ | \`navigation\` | 42,076 | 12,846 | 11,125 | 1,587 | 531 | 233 |
3782
+ | \`notifications\` | 60,428 | 17,470 | 15,447 | 15,559 | 4,000 | 3,056 |
3783
+ | \`number-input\` | 62,711 | 18,414 | 16,200 | 9,936 | 2,710 | 1,914 |
3784
+ | \`object-inspector\` | 107,211 | 33,688 | 29,397 | 26,855 | 7,376 | 5,779 |
3785
+ | \`option\` | 39,192 | 11,592 | 10,200 | 3,485 | 905 | 564 |
3786
+ | \`outline\` | 41,446 | 12,643 | 11,102 | 4,703 | 1,485 | 1,025 |
3787
+ | \`pagination\` | 121,340 | 36,006 | 31,403 | 38,967 | 9,843 | 7,657 |
3788
+ | \`pin-input\` | 56,225 | 16,427 | 14,415 | 6,212 | 1,940 | 1,209 |
3789
+ | \`popover\` | 72,247 | 23,560 | 20,556 | 3,678 | 1,122 | 667 |
3790
+ | \`progress\` | 37,937 | 11,449 | 10,052 | 2,409 | 803 | 484 |
3791
+ | \`qr-code\` | 50,196 | 16,089 | 14,139 | 14,937 | 5,517 | 4,541 |
3792
+ | \`quote\` | 35,535 | 10,672 | 9,341 | 552 | 293 | 133 |
3793
+ | \`radio\` | 55,852 | 16,358 | 14,260 | 3,954 | 1,196 | 751 |
3794
+ | \`rating\` | 60,609 | 18,068 | 15,805 | 7,789 | 2,398 | 1,708 |
3795
+ | \`scatter-chart\` | 90,002 | 28,914 | 25,377 | 13,985 | 4,210 | 3,261 |
3796
+ | \`scroll-area\` | 37,778 | 11,354 | 9,950 | 2,743 | 897 | 591 |
3797
+ | \`select\` | 106,032 | 32,233 | 28,217 | 23,738 | 6,133 | 4,792 |
3798
+ | \`skeleton\` | 36,541 | 10,963 | 9,654 | 1,190 | 453 | 126 |
3799
+ | \`skip-link\` | 36,698 | 11,106 | 9,705 | 1,562 | 631 | 311 |
3800
+ | \`slider\` | 57,787 | 16,802 | 14,802 | 7,357 | 2,094 | 1,438 |
3801
+ | \`sparkline\` | 43,547 | 13,471 | 11,798 | 2,387 | 913 | 631 |
3802
+ | \`speed-dial\` | 70,466 | 23,179 | 20,368 | 4,218 | 1,216 | 728 |
3803
+ | \`splitter\` | 50,411 | 14,864 | 13,103 | 10,977 | 2,906 | 2,217 |
3804
+ | \`stat\` | 36,863 | 10,988 | 9,645 | 1,511 | 493 | 222 |
3805
+ | \`steps\` | 55,412 | 16,440 | 14,377 | 8,459 | 2,323 | 1,635 |
3806
+ | \`switch\` | 52,608 | 15,403 | 13,513 | 1,790 | 676 | 308 |
3807
+ | \`table\` | 57,260 | 17,241 | 15,170 | 14,844 | 4,328 | 3,413 |
3808
+ | \`tabs\` | 49,298 | 14,722 | 12,809 | 4,025 | 1,047 | 747 |
3809
+ | \`tag\` | 47,772 | 14,598 | 12,861 | 5,626 | 1,674 | 1,136 |
3810
+ | \`textarea\` | 55,171 | 16,121 | 14,138 | 4,676 | 1,440 | 983 |
3811
+ | \`time-input\` | 148,716 | 43,305 | 37,532 | 43,009 | 10,737 | 8,330 |
3812
+ | \`time-picker\` | 85,174 | 24,617 | 21,538 | 27,375 | 7,292 | 5,587 |
3813
+ | \`timeline\` | 38,507 | 11,551 | 10,144 | 2,239 | 643 | 438 |
3814
+ | \`toast\` | 53,129 | 16,174 | 14,275 | 8,468 | 2,532 | 1,874 |
3815
+ | \`toggle\` | 59,077 | 17,265 | 15,114 | 5,356 | 1,515 | 1,001 |
3816
+ | \`toolbar\` | 43,517 | 13,332 | 11,648 | 4,134 | 1,427 | 851 |
3817
+ | \`tooltip\` | 71,070 | 22,939 | 20,172 | 8,345 | 2,401 | 1,737 |
3818
+ | \`tour\` | 87,778 | 27,527 | 24,134 | 15,948 | 4,335 | 3,270 |
3819
+ | \`tree\` | 54,810 | 16,530 | 14,410 | 8,344 | 2,414 | 1,763 |
3820
+ | \`trend\` | 38,098 | 11,560 | 10,156 | 2,213 | 709 | 384 |
3821
+ | \`video\` | 119,411 | 36,126 | 31,356 | 41,045 | 10,622 | 8,364 |
3822
+ | \`video-playlist\` | 92,641 | 28,852 | 25,227 | 17,519 | 4,309 | 3,217 |
3823
+ | \`virtual-list\` | 47,934 | 14,791 | 12,860 | 3,995 | 1,384 | 997 |
3641
3824
 
3642
3825
  ### Styled tier
3643
3826
 
@@ -3645,110 +3828,110 @@ The headless tier plus presentation. \`bun add @fusion.dev/helix\` installs this
3645
3828
 
3646
3829
  | Family | Alone raw | Alone gzip | Alone brotli | Added raw | Added gzip | Added brotli |
3647
3830
  |---|---|---|---|---|---|---|
3648
- | \`accordion\` | 97,484 | 31,527 | 25,776 | 6,204 | 1,540 | 1,328 |
3649
- | \`announcement\` | 96,325 | 30,966 | 25,283 | 6,133 | 1,434 | 1,318 |
3650
- | \`app-header\` | 39,037 | 11,664 | 10,286 | 5,121 | 1,173 | 1,019 |
3651
- | \`area-chart\` | 88,624 | 28,374 | 24,968 | 18,528 | 4,996 | 4,058 |
3652
- | \`aura\` | 102,182 | 34,152 | 29,605 | 65,492 | 23,022 | 19,750 |
3653
- | \`avatar\` | 40,820 | 12,142 | 10,694 | 6,872 | 1,666 | 1,415 |
3654
- | \`badge\` | 38,056 | 11,452 | 10,036 | 4,519 | 1,047 | 893 |
3655
- | \`bar-chart\` | 95,653 | 29,690 | 26,159 | 25,550 | 6,313 | 5,327 |
3656
- | \`blockquote\` | 35,853 | 11,018 | 9,681 | 1,914 | 481 | 403 |
3657
- | \`breadcrumbs\` | 94,168 | 30,039 | 24,642 | 5,518 | 1,237 | 1,066 |
3658
- | \`button\` | 45,627 | 13,160 | 11,597 | 9,435 | 2,012 | 1,659 |
3659
- | \`button-group\` | 36,229 | 10,990 | 9,645 | 2,320 | 527 | 443 |
3660
- | \`callout\` | 91,867 | 29,665 | 24,423 | 3,044 | 803 | 731 |
3661
- | \`canvas\` | 116,132 | 32,041 | 27,998 | 70,330 | 18,726 | 15,747 |
3662
- | \`card\` | 37,868 | 11,465 | 10,070 | 3,963 | 988 | 908 |
3663
- | \`carousel\` | 110,792 | 33,934 | 27,953 | 21,720 | 4,518 | 3,933 |
3664
- | \`chat\` | 127,645 | 39,596 | 32,691 | 31,592 | 7,644 | 6,509 |
3665
- | \`checkbox\` | 50,794 | 14,480 | 12,734 | 9,413 | 2,243 | 1,860 |
3666
- | \`checkbox-group\` | 49,591 | 14,307 | 12,571 | 7,692 | 1,940 | 1,568 |
3667
- | \`code\` | 34,249 | 10,492 | 9,227 | 1,511 | 372 | 429 |
3668
- | \`code-block\` | 152,056 | 47,072 | 39,635 | 33,873 | 7,293 | 6,180 |
3669
- | \`color-input\` | 187,784 | 53,477 | 45,370 | 60,032 | 11,436 | 9,730 |
3670
- | \`color-picker\` | 148,452 | 42,352 | 35,092 | 48,165 | 9,437 | 8,006 |
3671
- | \`combobox\` | 163,625 | 49,537 | 41,748 | 36,412 | 7,971 | 6,635 |
3672
- | \`command\` | 129,039 | 39,047 | 32,120 | 28,805 | 6,715 | 5,685 |
3673
- | \`copy-button\` | 140,190 | 44,376 | 37,397 | 22,010 | 4,707 | 3,910 |
3674
- | \`data-table\` | 227,144 | 64,440 | 54,220 | 95,535 | 21,432 | 17,484 |
3675
- | \`date-input\` | 162,787 | 49,388 | 41,706 | 35,359 | 7,915 | 6,652 |
3676
- | \`date-picker\` | 107,397 | 34,083 | 27,876 | 15,499 | 3,869 | 3,190 |
3677
- | \`description-list\` | 37,034 | 11,136 | 9,766 | 3,502 | 769 | 609 |
3678
- | \`dialog\` | 42,582 | 12,668 | 11,151 | 7,079 | 1,783 | 1,532 |
3679
- | \`divider\` | 37,059 | 11,328 | 9,883 | 3,120 | 770 | 646 |
3680
- | \`donut-chart\` | 88,088 | 27,652 | 24,389 | 19,422 | 4,911 | 4,172 |
3681
- | \`drawer\` | 41,221 | 12,297 | 10,794 | 6,007 | 1,482 | 1,303 |
3682
- | \`drilldown\` | 103,343 | 33,143 | 27,029 | 10,391 | 2,513 | 2,074 |
3683
- | \`empty\` | 36,590 | 11,298 | 9,906 | 2,380 | 703 | 620 |
3684
- | \`file-input\` | 113,670 | 35,206 | 28,887 | 17,794 | 4,073 | 3,440 |
3685
- | \`filter-input\` | 187,314 | 54,146 | 45,740 | 56,402 | 11,409 | 9,637 |
3686
- | \`flex\` | 35,610 | 10,843 | 9,523 | 2,078 | 453 | 408 |
3687
- | \`format-date\` | 38,814 | 11,918 | 10,519 | 3,498 | 870 | 748 |
3688
- | \`graph\` | 131,342 | 39,599 | 32,592 | 26,303 | 5,764 | 4,990 |
3689
- | \`grid\` | 36,203 | 11,032 | 9,705 | 2,667 | 625 | 643 |
3690
- | \`heatmap\` | 87,000 | 27,374 | 24,210 | 17,773 | 4,424 | 3,659 |
3691
- | \`icon\` | 89,994 | 29,073 | 23,848 | 1,707 | 413 | 305 |
3692
- | \`icon-button\` | 45,786 | 13,032 | 11,449 | 9,596 | 1,871 | 1,580 |
3693
- | \`image\` | 38,428 | 11,636 | 10,225 | 4,841 | 1,286 | 1,127 |
3694
- | \`input\` | 107,548 | 33,803 | 27,644 | 11,102 | 2,659 | 2,157 |
3695
- | \`kbd\` | 37,919 | 11,849 | 10,407 | 4,373 | 1,374 | 1,189 |
3696
- | \`legend\` | 43,375 | 13,019 | 11,400 | 5,790 | 1,390 | 1,086 |
3697
- | \`lightbox\` | 46,011 | 13,700 | 11,994 | 7,803 | 1,989 | 1,683 |
3698
- | \`line-chart\` | 90,551 | 28,485 | 25,135 | 20,543 | 5,162 | 4,264 |
3699
- | \`list\` | 39,692 | 11,750 | 10,324 | 5,799 | 1,305 | 1,114 |
3700
- | \`listbox\` | 114,516 | 36,116 | 29,507 | 15,768 | 4,063 | 3,221 |
3701
- | \`loader\` | 37,959 | 11,498 | 10,113 | 4,051 | 994 | 834 |
3702
- | \`map\` | 172,078 | 45,778 | 38,148 | 70,072 | 13,195 | 11,085 |
3703
- | \`megamenu\` | 69,973 | 22,584 | 19,936 | 9,806 | 2,358 | 1,997 |
3704
- | \`menu\` | 136,343 | 44,103 | 37,043 | 16,360 | 3,788 | 3,186 |
3705
- | \`meter\` | 43,381 | 12,723 | 11,220 | 9,480 | 2,236 | 1,914 |
3706
- | \`navigation\` | 38,193 | 11,742 | 10,282 | 3,051 | 805 | 620 |
3707
- | \`notifications\` | 118,939 | 36,071 | 29,612 | 24,488 | 5,037 | 4,312 |
3708
- | \`number-input\` | 108,991 | 34,360 | 28,086 | 12,537 | 3,136 | 2,557 |
3709
- | \`object-inspector\` | 157,035 | 49,044 | 41,504 | 33,323 | 7,594 | 6,393 |
3710
- | \`option\` | 40,102 | 12,078 | 10,643 | 6,203 | 1,566 | 1,334 |
3711
- | \`orb\` | 44,808 | 14,467 | 12,771 | 8,624 | 3,203 | 2,835 |
3712
- | \`outline\` | 43,651 | 13,234 | 11,681 | 8,351 | 2,119 | 1,758 |
3713
- | \`pagination\` | 170,448 | 50,616 | 42,743 | 45,787 | 9,637 | 7,927 |
3714
- | \`pin-input\` | 49,531 | 14,596 | 12,865 | 8,390 | 2,385 | 1,883 |
3715
- | \`popover\` | 64,967 | 21,370 | 18,901 | 4,552 | 1,174 | 989 |
3716
- | \`progress\` | 40,863 | 12,174 | 10,744 | 6,962 | 1,676 | 1,392 |
3717
- | \`qr-code\` | 48,148 | 15,475 | 13,623 | 14,629 | 5,257 | 4,395 |
3718
- | \`quote\` | 34,731 | 10,654 | 9,327 | 1,191 | 291 | 196 |
3719
- | \`radio\` | 54,213 | 14,925 | 13,136 | 11,161 | 2,283 | 1,940 |
3720
- | \`rating\` | 52,430 | 15,624 | 13,762 | 10,984 | 3,118 | 2,591 |
3721
- | \`sandbox\` | 70,095 | 18,502 | 16,381 | 35,720 | 7,874 | 6,656 |
3722
- | \`scatter-chart\` | 89,076 | 28,201 | 24,857 | 19,840 | 5,218 | 4,316 |
3723
- | \`scroll-area\` | 39,467 | 11,819 | 10,362 | 5,874 | 1,384 | 1,137 |
3724
- | \`select\` | 153,428 | 47,408 | 39,909 | 28,985 | 6,520 | 5,348 |
3725
- | \`skeleton\` | 35,783 | 10,981 | 9,631 | 2,242 | 595 | 512 |
3726
- | \`skip-link\` | 36,318 | 11,203 | 9,793 | 2,624 | 722 | 554 |
3727
- | \`slider\` | 57,985 | 15,794 | 13,935 | 16,691 | 3,552 | 3,037 |
3728
- | \`sparkline\` | 44,898 | 13,878 | 12,241 | 6,293 | 1,748 | 1,518 |
3729
- | \`speed-dial\` | 127,953 | 41,580 | 34,952 | 11,355 | 2,362 | 1,933 |
3730
- | \`splitter\` | 50,430 | 14,235 | 12,615 | 16,337 | 3,634 | 3,167 |
3731
- | \`stat\` | 38,466 | 11,378 | 10,026 | 4,565 | 917 | 795 |
3732
- | \`steps\` | 112,667 | 34,217 | 28,149 | 20,087 | 3,975 | 3,478 |
3733
- | \`switch\` | 47,784 | 13,981 | 12,292 | 6,002 | 1,571 | 1,310 |
3734
- | \`table\` | 106,565 | 34,049 | 27,890 | 15,748 | 3,973 | 3,393 |
3735
- | \`tabs\` | 48,895 | 14,049 | 12,334 | 10,154 | 2,153 | 1,799 |
3736
- | \`tag\` | 93,365 | 30,080 | 24,587 | 4,244 | 1,063 | 902 |
3737
- | \`text\` | 37,730 | 11,196 | 9,825 | 4,200 | 929 | 755 |
3738
- | \`textarea\` | 49,038 | 14,260 | 12,518 | 7,416 | 1,936 | 1,566 |
3739
- | \`time-input\` | 181,396 | 53,205 | 44,933 | 50,671 | 10,793 | 9,012 |
3740
- | \`time-picker\` | 130,570 | 39,823 | 32,809 | 30,854 | 7,358 | 6,136 |
3741
- | \`timeline\` | 93,763 | 29,912 | 24,574 | 5,110 | 1,131 | 1,009 |
3742
- | \`toast\` | 101,341 | 31,985 | 26,219 | 11,599 | 2,622 | 2,166 |
3743
- | \`toggle\` | 52,798 | 15,150 | 13,346 | 8,526 | 2,062 | 1,697 |
3744
- | \`toolbar\` | 37,939 | 11,649 | 10,233 | 3,899 | 1,022 | 835 |
3745
- | \`tooltip\` | 69,601 | 22,599 | 19,950 | 9,554 | 2,494 | 2,005 |
3746
- | \`tour\` | 81,996 | 24,885 | 21,973 | 20,795 | 4,496 | 3,706 |
3747
- | \`tree\` | 106,515 | 33,905 | 27,724 | 13,067 | 3,290 | 2,734 |
3748
- | \`trend\` | 92,548 | 29,698 | 24,397 | 4,271 | 983 | 799 |
3749
- | \`video\` | 176,566 | 52,762 | 44,815 | 51,979 | 11,228 | 9,627 |
3750
- | \`video-playlist\` | 150,421 | 46,636 | 39,232 | 29,040 | 5,998 | 5,029 |
3751
- | \`virtual-list\` | 41,389 | 12,879 | 11,334 | 3,187 | 935 | 716 |
3831
+ | \`accordion\` | 48,121 | 14,422 | 12,688 | 7,647 | 2,065 | 1,560 |
3832
+ | \`announcement\` | 45,485 | 13,478 | 11,811 | 6,169 | 1,548 | 1,222 |
3833
+ | \`app-header\` | 41,202 | 12,052 | 10,574 | 5,673 | 1,515 | 1,108 |
3834
+ | \`area-chart\` | 98,228 | 30,935 | 27,181 | 21,331 | 5,831 | 4,582 |
3835
+ | \`aura\` | 64,892 | 19,687 | 17,298 | 26,743 | 8,324 | 7,050 |
3836
+ | \`avatar\` | 44,061 | 12,836 | 11,293 | 7,891 | 2,116 | 1,661 |
3837
+ | \`badge\` | 40,439 | 11,760 | 10,311 | 5,445 | 1,325 | 1,001 |
3838
+ | \`bar-chart\` | 106,399 | 32,622 | 28,595 | 29,117 | 7,395 | 5,972 |
3839
+ | \`blockquote\` | 37,656 | 11,278 | 9,895 | 2,258 | 693 | 401 |
3840
+ | \`breadcrumbs\` | 42,077 | 12,357 | 10,859 | 5,799 | 1,446 | 1,054 |
3841
+ | \`button\` | 56,398 | 16,247 | 14,165 | 11,984 | 2,955 | 2,197 |
3842
+ | \`button-group\` | 37,688 | 11,167 | 9,792 | 2,320 | 688 | 446 |
3843
+ | \`callout\` | 45,299 | 13,583 | 11,889 | 5,248 | 1,441 | 1,084 |
3844
+ | \`canvas\` | 118,250 | 32,469 | 28,310 | 70,994 | 18,981 | 15,657 |
3845
+ | \`card\` | 40,909 | 12,065 | 10,599 | 5,378 | 1,439 | 1,060 |
3846
+ | \`carousel\` | 59,973 | 16,383 | 14,508 | 23,273 | 5,225 | 4,198 |
3847
+ | \`chat\` | 78,040 | 21,966 | 19,379 | 32,525 | 7,983 | 6,436 |
3848
+ | \`checkbox\` | 60,002 | 16,960 | 14,858 | 9,568 | 2,436 | 1,804 |
3849
+ | \`checkbox-group\` | 66,556 | 18,479 | 16,166 | 15,554 | 3,827 | 2,840 |
3850
+ | \`code\` | 35,708 | 10,676 | 9,358 | 1,511 | 510 | 280 |
3851
+ | \`code-block\` | 117,062 | 33,746 | 29,661 | 42,896 | 9,601 | 7,751 |
3852
+ | \`color-input\` | 161,920 | 43,479 | 38,020 | 72,998 | 15,074 | 12,421 |
3853
+ | \`color-picker\` | 119,011 | 31,025 | 27,241 | 59,934 | 12,942 | 10,570 |
3854
+ | \`combobox\` | 141,827 | 39,737 | 34,754 | 52,627 | 11,802 | 9,495 |
3855
+ | \`command\` | 98,519 | 26,850 | 23,518 | 38,807 | 9,390 | 7,486 |
3856
+ | \`copy-button\` | 103,331 | 30,817 | 26,998 | 29,157 | 6,650 | 5,227 |
3857
+ | \`data-table\` | 208,210 | 56,196 | 47,474 | 118,121 | 28,030 | 21,633 |
3858
+ | \`date-input\` | 157,188 | 43,280 | 37,801 | 55,567 | 11,971 | 9,704 |
3859
+ | \`date-picker\` | 69,815 | 19,452 | 17,281 | 24,462 | 5,777 | 4,561 |
3860
+ | \`description-list\` | 38,493 | 11,308 | 9,902 | 3,500 | 914 | 586 |
3861
+ | \`dialog\` | 54,741 | 16,320 | 14,276 | 10,551 | 2,885 | 2,204 |
3862
+ | \`divider\` | 38,940 | 11,591 | 10,168 | 3,542 | 990 | 652 |
3863
+ | \`donut-chart\` | 98,342 | 30,409 | 26,765 | 22,874 | 5,995 | 4,800 |
3864
+ | \`drawer\` | 55,007 | 16,412 | 14,381 | 9,604 | 2,677 | 2,095 |
3865
+ | \`drilldown\` | 56,968 | 16,933 | 14,788 | 11,056 | 2,834 | 2,148 |
3866
+ | \`empty\` | 38,473 | 11,578 | 10,099 | 2,613 | 857 | 561 |
3867
+ | \`file-input\` | 81,761 | 23,313 | 20,426 | 25,298 | 6,337 | 5,024 |
3868
+ | \`filter-input\` | 150,189 | 40,993 | 35,691 | 59,777 | 12,607 | 10,072 |
3869
+ | \`flex\` | 37,069 | 11,029 | 9,663 | 2,078 | 606 | 316 |
3870
+ | \`format-date\` | 42,448 | 12,721 | 11,225 | 4,932 | 1,384 | 975 |
3871
+ | \`graph\` | 83,721 | 23,127 | 20,248 | 29,634 | 7,367 | 5,805 |
3872
+ | \`grid\` | 38,524 | 11,590 | 10,202 | 3,533 | 1,152 | 854 |
3873
+ | \`heatmap\` | 100,985 | 31,285 | 27,393 | 21,043 | 5,417 | 4,248 |
3874
+ | \`icon\` | 94,226 | 29,533 | 25,208 | 56,405 | 19,564 | 15,360 |
3875
+ | \`icon-button\` | 57,339 | 16,168 | 14,140 | 12,926 | 2,896 | 2,176 |
3876
+ | \`image\` | 41,085 | 12,122 | 10,641 | 5,371 | 1,566 | 1,173 |
3877
+ | \`input\` | 63,649 | 18,692 | 16,286 | 11,927 | 3,565 | 2,565 |
3878
+ | \`kbd\` | 41,118 | 12,584 | 11,043 | 4,829 | 1,629 | 1,121 |
3879
+ | \`legend\` | 47,965 | 14,166 | 12,383 | 7,671 | 2,046 | 1,442 |
3880
+ | \`lightbox\` | 57,296 | 16,525 | 14,566 | 12,850 | 3,300 | 2,482 |
3881
+ | \`line-chart\` | 101,137 | 31,376 | 27,585 | 24,094 | 6,226 | 5,072 |
3882
+ | \`list\` | 41,331 | 11,967 | 10,518 | 5,976 | 1,490 | 1,177 |
3883
+ | \`listbox\` | 76,796 | 22,106 | 19,326 | 20,975 | 5,632 | 4,354 |
3884
+ | \`loader\` | 41,425 | 12,238 | 10,760 | 5,242 | 1,484 | 1,079 |
3885
+ | \`map\` | 125,915 | 30,054 | 26,073 | 75,034 | 15,543 | 12,270 |
3886
+ | \`megamenu\` | 72,426 | 23,061 | 20,296 | 10,031 | 2,594 | 1,911 |
3887
+ | \`menu\` | 92,016 | 28,697 | 25,105 | 18,272 | 4,491 | 3,413 |
3888
+ | \`meter\` | 46,018 | 13,184 | 11,630 | 10,472 | 2,578 | 2,052 |
3889
+ | \`navigation\` | 43,728 | 13,312 | 11,528 | 3,221 | 1,022 | 622 |
3890
+ | \`notifications\` | 73,708 | 19,871 | 17,586 | 28,831 | 6,427 | 5,267 |
3891
+ | \`number-input\` | 67,684 | 19,551 | 17,221 | 14,890 | 3,876 | 2,953 |
3892
+ | \`object-inspector\` | 122,792 | 36,326 | 31,725 | 42,419 | 10,058 | 8,043 |
3893
+ | \`option\` | 42,446 | 12,501 | 11,019 | 6,725 | 1,813 | 1,295 |
3894
+ | \`orb\` | 46,363 | 14,669 | 12,905 | 8,724 | 3,373 | 2,779 |
3895
+ | \`outline\` | 45,186 | 13,419 | 11,785 | 8,426 | 2,301 | 1,717 |
3896
+ | \`pagination\` | 139,323 | 39,095 | 34,021 | 56,933 | 12,979 | 10,410 |
3897
+ | \`pin-input\` | 59,673 | 17,283 | 15,193 | 9,643 | 2,818 | 2,023 |
3898
+ | \`popover\` | 75,869 | 24,333 | 21,264 | 7,282 | 1,936 | 1,356 |
3899
+ | \`progress\` | 43,533 | 12,712 | 11,219 | 7,987 | 2,083 | 1,600 |
3900
+ | \`qr-code\` | 51,860 | 16,518 | 14,502 | 16,585 | 5,954 | 4,865 |
3901
+ | \`quote\` | 36,215 | 10,843 | 9,481 | 1,216 | 460 | 197 |
3902
+ | \`radio\` | 64,144 | 17,850 | 15,648 | 12,236 | 2,730 | 2,072 |
3903
+ | \`rating\` | 64,926 | 19,300 | 16,928 | 12,084 | 3,628 | 2,814 |
3904
+ | \`sandbox\` | 77,010 | 20,452 | 17,994 | 37,272 | 8,465 | 6,969 |
3905
+ | \`scatter-chart\` | 98,869 | 30,809 | 27,023 | 22,828 | 6,117 | 4,881 |
3906
+ | \`scroll-area\` | 40,926 | 11,999 | 10,508 | 5,874 | 1,556 | 1,077 |
3907
+ | \`select\` | 118,886 | 34,630 | 30,262 | 36,578 | 8,554 | 6,822 |
3908
+ | \`skeleton\` | 39,347 | 11,644 | 10,257 | 3,981 | 1,150 | 791 |
3909
+ | \`skip-link\` | 38,161 | 11,506 | 10,081 | 3,008 | 1,022 | 664 |
3910
+ | \`slider\` | 68,867 | 18,804 | 16,589 | 18,420 | 4,147 | 3,205 |
3911
+ | \`sparkline\` | 47,474 | 14,421 | 12,684 | 6,294 | 1,882 | 1,503 |
3912
+ | \`speed-dial\` | 134,519 | 43,564 | 36,886 | 66,341 | 21,581 | 17,007 |
3913
+ | \`splitter\` | 56,483 | 15,850 | 13,987 | 17,031 | 3,967 | 3,124 |
3914
+ | \`stat\` | 40,443 | 11,709 | 10,282 | 5,081 | 1,229 | 889 |
3915
+ | \`steps\` | 70,250 | 19,157 | 16,771 | 23,289 | 5,099 | 4,082 |
3916
+ | \`switch\` | 57,461 | 16,577 | 14,545 | 6,627 | 1,858 | 1,342 |
3917
+ | \`table\` | 63,029 | 18,409 | 16,244 | 20,603 | 5,526 | 4,454 |
3918
+ | \`tabs\` | 55,917 | 16,074 | 14,020 | 10,629 | 2,426 | 1,812 |
3919
+ | \`tag\` | 52,749 | 15,717 | 13,896 | 10,588 | 2,807 | 2,044 |
3920
+ | \`text\` | 40,992 | 11,800 | 10,350 | 6,004 | 1,453 | 998 |
3921
+ | \`textarea\` | 58,889 | 17,042 | 14,926 | 8,378 | 2,391 | 1,704 |
3922
+ | \`time-input\` | 172,753 | 47,297 | 40,980 | 67,030 | 14,784 | 11,821 |
3923
+ | \`time-picker\` | 96,904 | 26,815 | 23,494 | 39,096 | 9,543 | 7,544 |
3924
+ | \`timeline\` | 41,820 | 12,294 | 10,765 | 5,538 | 1,397 | 1,058 |
3925
+ | \`toast\` | 61,343 | 17,944 | 15,845 | 16,665 | 4,368 | 3,382 |
3926
+ | \`toggle\` | 64,719 | 18,533 | 16,240 | 10,987 | 2,817 | 2,127 |
3927
+ | \`toolbar\` | 44,810 | 13,631 | 11,889 | 5,409 | 1,735 | 1,212 |
3928
+ | \`tooltip\` | 74,148 | 23,682 | 20,846 | 11,405 | 3,162 | 2,426 |
3929
+ | \`tour\` | 99,455 | 29,632 | 26,015 | 27,607 | 6,491 | 5,087 |
3930
+ | \`tree\` | 60,660 | 17,892 | 15,658 | 14,183 | 3,823 | 2,941 |
3931
+ | \`trend\` | 39,907 | 12,024 | 10,551 | 4,003 | 1,179 | 874 |
3932
+ | \`video\` | 137,129 | 39,344 | 34,264 | 58,747 | 13,884 | 11,183 |
3933
+ | \`video-playlist\` | 105,059 | 31,036 | 27,158 | 29,919 | 6,565 | 5,145 |
3934
+ | \`virtual-list\` | 48,726 | 15,007 | 13,061 | 4,770 | 1,587 | 1,099 |
3752
3935
 
3753
3936
  ## What an install adds to \`node_modules\`
3754
3937
 
@@ -3760,18 +3943,18 @@ stripped column shows the bytes we removed.
3760
3943
 
3761
3944
  | Package | Unpacked | Files | Source maps stripped | Runtime dependencies |
3762
3945
  |---|---|---|---|---|
3763
- | \`@fusion.dev/helix-core\` | 1,219,204 | 179 | 274,659 | \`@floating-ui/dom\`, \`@fusion.dev/helix-icons\` |
3764
- | \`@fusion.dev/helix-headless\` | 13,709,247 | 511 | 1,079,071 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-icons\`, \`uqr\` |
3765
- | \`@fusion.dev/helix-icons\` | 150,162 | 21 | 50,346 | \`svgo\` |
3766
- | \`@fusion.dev/helix-styles\` | 106,097 | 6 | 0 | none |
3946
+ | \`@fusion.dev/helix-core\` | 1,637,132 | 231 | 417,937 | \`@floating-ui/dom\`, \`@fusion.dev/helix-icons\` |
3947
+ | \`@fusion.dev/helix-headless\` | 15,882,414 | 561 | 1,363,913 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-icons\`, \`uqr\` |
3948
+ | \`@fusion.dev/helix-icons\` | 149,615 | 21 | 47,843 | \`svgo\` |
3949
+ | \`@fusion.dev/helix-styles\` | 106,152 | 6 | 0 | none |
3767
3950
  | \`@fusion.dev/helix-theme\` | 528,598 | 8 | 5,393 | none |
3768
- | \`@fusion.dev/helix\` | 14,852,492 | 877 | 373,887 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-headless\`, \`@fusion.dev/helix-styles\` |
3951
+ | \`@fusion.dev/helix\` | 16,571,414 | 885 | 383,770 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-headless\`, \`@fusion.dev/helix-styles\` |
3769
3952
 
3770
3953
  ## Not measured yet
3771
3954
 
3772
3955
  We list these gaps so you know what the numbers above leave out.
3773
3956
 
3774
- - **No whole-library comparison, and no more than five components.** The comparison above covers five components in four systems. Adding a component means choosing the matching element in each system by hand, so we add components one at a time.
3957
+ - **No whole-library comparison, and a short list of components.** Adding a component means choosing the matching element in each system by hand, so we add components one at a time.
3775
3958
  - **The peer numbers are pinned, so they age.** The comparison shows the date they were measured. Run \`turbo run peers\` to refresh them. No check fails when they are old. Another library's release changes nothing in this repository, so a check based on the date would fail for no useful reason.
3776
3959
  - **No first paint.** The timings above measure single components. First paint depends on the whole page, so the app that renders the page should measure it.
3777
3960
  - **No per-component stylesheet bytes.** Each family's CSS is compiled into its JavaScript, so every number above already includes it. \`elements.css\` is the light-DOM layer, and it is in the stylesheet table.
@@ -3943,10 +4126,11 @@ it.
3943
4126
  ## Register the elements
3944
4127
 
3945
4128
  \`\`\`ts
3946
- import '@fusion.dev/helix'
4129
+ import '@fusion.dev/helix/button'
4130
+ import '@fusion.dev/helix/dialog'
3947
4131
  \`\`\`
3948
4132
 
3949
- Import it once, anywhere that runs in the browser. The stylesheets are the same
4133
+ Import each family you use once, anywhere that runs in the browser. The stylesheets are the same
3950
4134
  in every framework, and they are the part most often left out. See
3951
4135
  [Installation](./installation) for the stylesheets.
3952
4136
  `,
@@ -4022,17 +4206,44 @@ checks focus by walking through the shadow roots.
4022
4206
  Nested overlays work because lifecycle events do not bubble.
4023
4207
  \`helix-before-open\` and \`helix-before-close\` do not bubble and are not composed,
4024
4208
  so a menu that closes inside a dialog does not close the dialog. \`Escape\` closes
4025
- the innermost overlay and leaves the others open.
4209
+ the innermost overlay and leaves the others open. The overlay that closes
4210
+ cancels the key press, so a \`Dialog\` or \`Drawer\` around it stays open until you
4211
+ press \`Escape\` again.
4026
4212
 
4027
4213
  ## Where focus goes
4028
4214
 
4029
4215
  A modal overlay keeps \`Tab\` inside itself while it is open, and it returns focus
4030
- to the element that opened it. \`Dialog\` and \`Drawer\` always do this. \`Popover\`
4031
- does it only in its modal mode.
4216
+ to the element that opened it. \`Dialog\` does this, and so does \`Drawer\` unless
4217
+ you set \`modal="false"\`. The page behind a modal \`Dialog\` or \`Drawer\` does not
4218
+ scroll while it is open.
4219
+
4220
+ Opening a \`Popover\` moves focus to the first control in its panel, or to the
4221
+ panel where it holds none, and closing it from inside gives focus back to the
4222
+ trigger. It does not trap focus unless you set \`modal\`, which keeps \`Tab\` in the
4223
+ panel until it closes. When focus moves out of its trigger and its panel, the
4224
+ popover closes.
4225
+
4226
+ Press F8 to move focus to the \`Toast\` stack, and press it again to go back.
4227
+ Set \`hotkey\` on the stack to use another key. The stack's name says which key
4228
+ it is.
4229
+
4230
+ The fields with a panel behave the same way:
4231
+
4232
+ - \`Select\` and \`Combobox\` close their list when \`Tab\` moves focus out.
4233
+ - \`Date Input\`, \`Time Input\`, and \`Color Input\` close their panel when focus
4234
+ leaves the field, and \`Escape\` returns focus to the field.
4235
+ - Opening one of those panels from its trigger, or with \`ArrowDown\`, moves
4236
+ focus into the panel.
4032
4237
 
4033
4238
  **A tooltip never takes focus.** A tooltip only describes a control, so it
4034
4239
  cannot contain a button. For something with a button in it, use a \`Popover\`.
4035
4240
 
4241
+ A tooltip describes its trigger by itself, whether it wraps the trigger or
4242
+ names it with \`for\`. A Helix trigger is described as soon as it has rendered.
4243
+ A plain element in your markup is described the first time a reader points at
4244
+ it or focuses it, so the link is never written into markup your server sent.
4245
+ Write \`aria-describedby\` yourself to have the link in the server's markup.
4246
+
4036
4247
  ## Keep an overlay open
4037
4248
 
4038
4249
  An overlay sends \`helix-before-close\` before it closes. Cancel the event to keep
@@ -4056,6 +4267,20 @@ on the \`overlay\` and \`display\` properties, which allows an exit animation on
4056
4267
  element the browser is about to remove from the top layer. Every overlay
4057
4268
  responds to \`prefers-reduced-motion\`.
4058
4269
 
4270
+ \`Dialog\` and \`Drawer\` also say where they are in the journey:
4271
+ \`:state(entering)\` holds from the moment they open until their entrance has
4272
+ finished, and \`:state(exiting)\` from the moment they close until their exit has
4273
+ finished. Select on them to draw an entrance or an exit of your own.
4274
+
4275
+ ## Swiping an overlay away
4276
+
4277
+ A touch or a pen swipes a \`Drawer\` toward the edge it came from, and a \`Toast\`
4278
+ message toward the end of the line. A swipe past halfway, or a quick one, closes
4279
+ it through the same cancelable request as its close control. A \`Drawer\` with
4280
+ \`snap-points\` comes to rest at the nearest point, such as half open. In a
4281
+ \`Lightbox\`, a swipe across the viewer shows the next or the previous item. A
4282
+ mouse never swipes, because dragging with a mouse selects text.
4283
+
4059
4284
  ## Choose an overlay
4060
4285
 
4061
4286
  | Component | Use it for |
@@ -4379,7 +4604,9 @@ See [State and control](./state-and-control) for the full model.
4379
4604
 
4380
4605
  \`\`\`tsx
4381
4606
  'use client'
4382
- import '@fusion.dev/helix'
4607
+ // One line per family you use.
4608
+ import '@fusion.dev/helix/button'
4609
+ import '@fusion.dev/helix/dialog'
4383
4610
 
4384
4611
  export const HelixElements = () => null
4385
4612
  \`\`\`
@@ -4852,20 +5079,84 @@ without tracking which element sent each event. A pane named \`html\` sets the
4852
5079
  preview's markup, and a pane named \`css\` sets its stylesheet. The sandbox
4853
5080
  ignores a pane with any other name, so that pane only displays its contents.
4854
5081
 
5082
+ A pane's text goes in its \`value\`. The pane renders no children. The sandbox
5083
+ also hands each pane's \`value\` to the preview when it starts, so you write the
5084
+ text once, in the pane. A preview given its own \`source\` keeps it until the
5085
+ first edit.
5086
+
4855
5087
  \`\`\`html
4856
5088
  <helix-sandbox>
4857
5089
  <helix-sandbox-source
4858
5090
  name="html"
4859
5091
  slot="source"
4860
- >…</helix-sandbox-source>
5092
+ value="<p>Hello</p>"
5093
+ ></helix-sandbox-source>
4861
5094
  <helix-sandbox-source
4862
5095
  name="css"
4863
5096
  slot="source"
4864
- >…</helix-sandbox-source>
4865
- <helix-sandbox-preview slot="preview"></helix-sandbox-preview>
5097
+ value="p { color: teal }"
5098
+ ></helix-sandbox-source>
5099
+ <helix-sandbox-preview
5100
+ slot="preview"
5101
+ src="/frame.html"
5102
+ ></helix-sandbox-preview>
4866
5103
  </helix-sandbox>
4867
5104
  \`\`\`
4868
5105
 
5106
+ Cancel \`helix-before-edit\` to refuse an edit. The pane keeps its text, and the
5107
+ preview does not receive the refused one.
5108
+
5109
+ In a source pane, Tab inserts two spaces. Shift+Tab moves focus back, and
5110
+ Escape then Tab moves it forward. The field's description says this to a
5111
+ screen reader.
5112
+
5113
+ ## The frame document
5114
+
5115
+ \`helix-sandbox-preview\` loads \`src\` into a sandboxed frame. You provide that
5116
+ document. It loads the styles and the elements your examples use, and it talks
5117
+ to the preview through \`postMessage\`:
5118
+
5119
+ | Message | Sent by | What it carries |
5120
+ |---|---|---|
5121
+ | \`helix-preview-console\` | The frame | One console call: \`level\` (\`log\`, \`info\`, \`warn\` or \`error\`) and \`text\` |
5122
+ | \`helix-preview-press\` | The frame | Nothing. Send it on \`pointerdown\`, so menus outside the frame close |
5123
+ | \`helix-preview-ready\` | The frame | Nothing. Send it once the listener for renders is in place |
5124
+ | \`helix-preview-render\` | The preview | \`source\`, \`styles\`, \`layout\`, \`direction\` and an optional \`colorMode\` |
5125
+ | \`helix-preview-size\` | The frame | \`size\`, the height of the content in CSS pixels |
5126
+
5127
+ Each message is an object with a \`type\` naming it. The preview sends
5128
+ \`helix-preview-render\` once the frame posts \`helix-preview-ready\` or fires
5129
+ \`load\`, and again after each edit settles. The frame writes \`source\` into its
5130
+ body and \`styles\` into a stylesheet. The preview accepts a message only from
5131
+ its own frame, and only from an opaque origin, so the frame keeps the sandbox
5132
+ it was given. The types are exported from \`@fusion.dev/helix/sandbox\` as
5133
+ \`PreviewMessage\` and its members.
5134
+
5135
+ A minimal frame follows. \`/helix.css\` is the stylesheet from
5136
+ \`@fusion.dev/helix-styles\`, and \`/elements.js\` is a classic script that
5137
+ registers your elements, for the reason under "How the preview is isolated".
5138
+
5139
+ \`\`\`html
5140
+ <!doctype html>
5141
+ <link
5142
+ href="/helix.css"
5143
+ rel="stylesheet"
5144
+ >
5145
+ <script
5146
+ defer
5147
+ src="/elements.js"
5148
+ ></script>
5149
+ <style id="example-styles"></style>
5150
+ <script defer>
5151
+ addEventListener('message', ({ data }) => {
5152
+ if (data?.type !== 'helix-preview-render') return
5153
+ document.getElementById('example-styles').textContent = data.styles
5154
+ document.body.innerHTML = data.source
5155
+ })
5156
+ parent.postMessage({ type: 'helix-preview-ready' }, '*')
5157
+ </script>
5158
+ \`\`\`
5159
+
4869
5160
  ## Console output from the example
4870
5161
 
4871
5162
  Logs from the example appear in the console panel. Logs from the page around it
@@ -4940,7 +5231,7 @@ browser. Load Lit's hydration support before the components:
4940
5231
 
4941
5232
  \`\`\`ts
4942
5233
  import '@lit-labs/ssr-client/lit-element-hydrate-support.js'
4943
- import '@fusion.dev/helix'
5234
+ import '@fusion.dev/helix/button'
4944
5235
  \`\`\`
4945
5236
 
4946
5237
  Hydration assumes the markup already matches the client's first render. If a
@@ -5454,6 +5745,12 @@ current value. The pair comes from the platform. A native input reflects its
5454
5745
  \`value\` *content attribute* to \`defaultValue\`, and it keeps a dirty flag. Once a
5455
5746
  user has typed, the flag stops the attribute from changing the value.
5456
5747
 
5748
+ **A form reset clears a \`value\` or \`checked\` you wrote in markup.** A native
5749
+ \`<input value="Ada">\` resets to \`Ada\`, and \`<helix-input value="Ada">\` resets to
5750
+ empty, because a Helix control resets to \`default-value\` and \`default-checked\`.
5751
+ Write the starting value of a form control as \`default-value\`, or
5752
+ \`default-checked\` for a checkbox or a switch.
5753
+
5457
5754
  ## State is published as a custom state
5458
5755
 
5459
5756
  \`\`\`css
@@ -5468,7 +5765,8 @@ A reflected \`value\` would carry the password past every session-replay masker
5468
5765
  that masks \`.value\` and \`input[value]\`.
5469
5766
 
5470
5767
  Helix publishes the resolved boolean as a custom state, and the attribute keeps
5471
- the value you wrote. There are four custom states:
5768
+ the value you wrote. These are the most common, and each component's reference
5769
+ page lists the states it publishes:
5472
5770
 
5473
5771
  - \`:state(open)\`
5474
5772
  - \`:state(checked)\`
@@ -5625,7 +5923,7 @@ and you do not need a compiler flag.
5625
5923
  Svelte passes objects and arrays as properties on its own:
5626
5924
 
5627
5925
  \`\`\`svelte
5628
- <helix-tabs items={tabs} />
5926
+ <helix-data-table label="People" rows={people} />
5629
5927
  \`\`\`
5630
5928
 
5631
5929
  Svelte's own attributes are typed on every Helix tag as well, so \`onclick\`,
@@ -5928,7 +6226,11 @@ Mark the section so the stylesheet derives its own colors there from the
5928
6226
  section's seeds, in the section's mode, and paint it with its page color:
5929
6227
 
5930
6228
  \`\`\`html
5931
- <section data-band data-color-mode="dark" data-helix-theme>…</section>
6229
+ <section
6230
+ data-band
6231
+ data-color-mode="dark"
6232
+ data-helix-theme
6233
+ >…</section>
5932
6234
  \`\`\`
5933
6235
 
5934
6236
  \`\`\`css
@@ -6504,7 +6806,7 @@ looks enabled while it does not accept input.
6504
6806
 
6505
6807
  \`\`\`ts
6506
6808
  import '@fusion.dev/helix-styles/helix.css'
6507
- import '@fusion.dev/helix'
6809
+ import '@fusion.dev/helix/button'
6508
6810
  \`\`\`
6509
6811
 
6510
6812
  \`helix.css\` combines four files in the order they must load:
@@ -6741,10 +7043,12 @@ button.
6741
7043
  ## Import \`elements.css\` beside the base layer
6742
7044
 
6743
7045
  \`\`\`ts
6744
- import '@fusion.dev/helix-styles/base.css'
6745
7046
  import '@fusion.dev/helix-styles/helix.css'
6746
7047
  \`\`\`
6747
7048
 
7049
+ \`helix.css\` imports \`elements.css\` after the primitives, the tokens, and the
7050
+ base layer. If you import the layers one at a time, import \`elements.css\` last.
7051
+
6748
7052
  \`elements.css\` hides each tag with \`:not(:defined)\` until the element upgrades.
6749
7053
  It uses \`visibility\`, so the page does not reflow. Without it, a card appears as
6750
7054
  unstyled text and then jumps into its card layout.
@@ -6763,6 +7067,24 @@ import '@fusion.dev/helix' // ❌ the barrel
6763
7067
  Import one component family per module, so you do not ship the whole library to
6764
7068
  use a button.
6765
7069
 
7070
+ ## Turn off an attribute that is on by default
7071
+
7072
+ A boolean attribute is off until you write it, with four exceptions. These are
7073
+ on until you write the string \`"false"\`:
7074
+
7075
+ - \`modal\` on Drawer
7076
+ - \`playsinline\` on Video
7077
+ - \`default-pinned\` on Chat
7078
+ - \`tab-indents\` on Sandbox Source
7079
+
7080
+ \`\`\`html
7081
+ <helix-drawer modal="false"></helix-drawer>
7082
+ \`\`\`
7083
+
7084
+ In JSX, \`modal={false}\` sets the property and does the same. Other features
7085
+ that are on by default turn off with an attribute named \`no-\`, such as
7086
+ \`no-copy\`.
7087
+
6766
7088
  ## Declarative shadow DOM is opt-in
6767
7089
 
6768
7090
  The site ships no declarative shadow DOM (DSD). The shadow styles load with the
@@ -7205,7 +7527,8 @@ That works for every Helix element. A string goes through either path, and an
7205
7527
  array or an object goes through the property.
7206
7528
 
7207
7529
  \`\`\`vue
7208
- <helix-tabs :items="items" @helix-before-activate="onActivate" />
7530
+ <helix-data-table label="People" :rows="people" />
7531
+ <helix-tabs @helix-before-activate="onActivate" />
7209
7532
  \`\`\`
7210
7533
 
7211
7534
  \`@helix-before-activate\` binds with \`addEventListener\`, so use the event's own