@fusion.dev/helix-headless 0.174.0 → 0.175.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-headless",
3
3
  "description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
4
- "version": "0.174.0",
4
+ "version": "0.175.0",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -49,13 +49,13 @@
49
49
  },
50
50
  "bugs": "https://github.com/project-fusion/fusion/issues",
51
51
  "dependencies": {
52
- "@fusion.dev/helix-core": "0.174.0",
53
- "@fusion.dev/helix-icons": "0.174.0",
52
+ "@fusion.dev/helix-core": "0.175.0",
53
+ "@fusion.dev/helix-icons": "0.175.0",
54
54
  "uqr": "^0.1.3"
55
55
  },
56
56
  "devDependencies": {
57
- "@fusion.dev/helix-cem": "0.174.0",
58
- "@fusion.dev/helix-testing": "0.174.0",
57
+ "@fusion.dev/helix-cem": "0.175.0",
58
+ "@fusion.dev/helix-testing": "0.175.0",
59
59
  "@fusion.dev/scripts": "0.0.0-dev",
60
60
  "@happy-dom/global-registrator": "^20.14.5",
61
61
  "@lit-labs/ssr": "^4.1.0",
package/types/jsx.d.ts CHANGED
@@ -17398,7 +17398,8 @@ Written by the root, which is the only thing that sees the set. */
17398
17398
  /** The item's name. It names the item's group, and fills `{label}` in the
17399
17399
  lightbox's `status-label`. */
17400
17400
  label?: (HelixHeadlessLightboxItem["label"]) | undefined;
17401
- /** The item's identifier. The root compares its `active` value against it. */
17401
+ /** The item's identifier. The root compares its `active` value against it.
17402
+ Without one, the item is named by its place in the set, counted from 1. */
17402
17403
  value?: (HelixHeadlessLightboxItem["value"]) | undefined;
17403
17404
  };
17404
17405
 
@@ -17410,7 +17411,8 @@ Written by the root, which is the only thing that sees the set. */
17410
17411
  /** The item's name. It names the item's group, and fills `{label}` in the
17411
17412
  lightbox's `status-label`. */
17412
17413
  "prop:label"?: (HelixHeadlessLightboxItem["label"]) | undefined;
17413
- /** The item's identifier. The root compares its `active` value against it. */
17414
+ /** The item's identifier. The root compares its `active` value against it.
17415
+ Without one, the item is named by its place in the set, counted from 1. */
17414
17416
  "prop:value"?: (HelixHeadlessLightboxItem["value"]) | undefined;
17415
17417
 
17416
17418
  /** Set the innerHTML of the element */
@@ -43330,8 +43332,10 @@ export type CustomElements = {
43330
43332
  * the full list. Combobox and Select do the same. As typing narrows the list, a
43331
43333
  * screen reader hears how many commands are left, such as "3 commands".
43332
43334
  *
43333
- * **Keyboard.** Focus goes to the filter field as the palette opens, and the
43334
- * highlight moves through the commands while you type.
43335
+ * **Keyboard.** Focus goes to the filter field as the palette opens, with no
43336
+ * command highlighted, as in React Aria's Autocomplete, so Enter runs nothing
43337
+ * until you type or press Down. Typing highlights the first command left, and
43338
+ * the highlight moves through the commands while you type.
43335
43339
  *
43336
43340
  * | Key | What it does |
43337
43341
  * |---|---|
@@ -49867,6 +49871,7 @@ export type CustomElements = {
49867
49871
  * - `label`: The item's name. It names the item's group, and fills `{label}` in the
49868
49872
  * lightbox's `status-label`.
49869
49873
  * - `value`: The item's identifier. The root compares its `active` value against it.
49874
+ * Without one, the item is named by its place in the set, counted from 1.
49870
49875
  * - `whenSettled`: Resolves a frame after the first update, when transitions are switched on.
49871
49876
  *
49872
49877
  * **Named `whenSettled` because `settled` is taken four times over**, by
@@ -49926,7 +49931,9 @@ export type CustomElements = {
49926
49931
  *
49927
49932
  * A lightbox shows one item at a time and has no scrolling track, so `active`
49928
49933
  * holds the current item, as in `Tabs`. The arrow keys change the item while
49929
- * focus stays in the dialog.
49934
+ * focus stays in the dialog. `active` names an item by its `value`, and an
49935
+ * item with no `value` by its place, counted from 1, as in `Steps`, so a set
49936
+ * written without values moves and `helix-activate` says `1`, `2` and so on.
49930
49937
  *
49931
49938
  * Set `controls` for the viewer's own previous, next and close controls, named
49932
49939
  * by `previous-label`, `next-label` and `dismiss-label`, whose glyphs you can
@@ -49943,9 +49950,9 @@ export type CustomElements = {
49943
49950
  * `--lightbox-pan-x` and `--lightbox-pan-y`, written only while zoomed, and a
49944
49951
  * swipe moves to the next item only while the item is at its own size. With
49945
49952
  * `controls`, the viewer also draws zoom-out and zoom-in controls, for a
49946
- * pointer with no wheel and no second finger. Once a reader stops zooming, the
49947
- * live region says the new scale in the words of `zoom-status-label`, such as
49948
- * "Zoomed to 150%".
49953
+ * pointer with no wheel and no second finger. Once a reader stops zooming, and
49954
+ * at once for a key or a zoom control, the live region says the new scale in
49955
+ * the words of `zoom-status-label`, such as "Zoomed to 150%".
49949
49956
  *
49950
49957
  * Each item is a slide: a `group` with the role description in
49951
49958
  * `slide-role-label`, named by its `label` or by `slide-label`. A touch or a pen
@@ -50108,15 +50115,10 @@ export type CustomElements = {
50108
50115
  * - `previous() => void`: Shows the previous item. Before the first item, it shows the last when
50109
50116
  * `loop` is set.
50110
50117
  * - `toggleFullscreen() => void`: Makes the viewer fill the screen, or exits fullscreen.
50111
- * - `requestActive(next: string, cause?: string) => boolean`: Requests a new current item, and returns whether the change was applied.
50118
+ * - `requestActive(next: string, cause?: string) => boolean`: Requests a new shown item, and returns whether it moved.
50112
50119
  *
50113
- * Announces before it acts, so `preventDefault()` on the `helix-before-activate` is
50114
- * a refusal and nothing moves. Unlike a native control, nothing has moved
50115
- * by the time this runs, so refusing is simply not writing: there is
50116
- * nothing to put back. Nobody refusing means the set updates itself,
50117
- * whether or not a consumer declared `active`, a declared property being a
50118
- * seed and a correction. `cause` says why, where the family names its
50119
- * causes, and reaches the event as `detail.cause`.
50120
+ * Where `active` names nothing, it is first written with the item on
50121
+ * screen, so `helix-activate` names the item you saw as `previous`.
50120
50122
  * - `requestOpen(next: boolean) => boolean`: Requests that the element open or close, and returns whether the change
50121
50123
  * was applied.
50122
50124
  *
@@ -53905,8 +53907,9 @@ export type CustomElements = {
53905
53907
  * the items and written to an attribute, so a stylesheet and a badge can both
53906
53908
  * use it without counting.
53907
53909
  *
53908
- * **The feed is one `Tab` stop for its rows.** Each row takes focus itself and
53909
- * is read by its label. `ArrowDown` and `ArrowUp` move to the next and the
53910
+ * **The feed is one `Tab` stop for its rows.** It is an APG feed: the list is
53911
+ * a `feed`, busy while `loading` is set, and each row is an `article` that
53912
+ * takes focus itself and is read by its label. `ArrowDown` and `ArrowUp` move to the next and the
53910
53913
  * previous row, `Home` and `End` to the first and the last, and `PageDown` and
53911
53914
  * `PageUp` move a row on or back from anywhere inside one, as in the APG feed
53912
53915
  * pattern. The controls inside a row stay in the `Tab` order. Set `total` when
@@ -54086,7 +54089,7 @@ export type CustomElements = {
54086
54089
  * - `error`: Shown while `load-error` is set, under any rows there are, in place of the empty and loading lines.
54087
54090
  * - `footer`: The region below the list.
54088
54091
  * - `header`: The region above the list.
54089
- * - `list`: The list itself.
54092
+ * - `list`: The list itself, a `feed` whose rows are its articles.
54090
54093
  * - `live`: A copy of the empty, loading and error messages, in a live region that screen readers announce when they change. Visually hidden in the styled tier.
54091
54094
  * - `loading`: Shown while the feed is loading.
54092
54095
  * - `mark-all`: The control that marks everything read.
@@ -63950,8 +63953,11 @@ export type CustomElements = {
63950
63953
  * markup is described when you first point at it or focus it, so a screen
63951
63954
  * reader in reading mode meets it with no description until then. Where the
63952
63955
  * browser has no element references, nothing links the two, and the tooltip
63953
- * warns once on first open. The tooltip can also wrap its trigger, which
63954
- * describes a Helix component and leaves a plain element undescribed. In the
63956
+ * warns once on first open. The tooltip can also wrap its trigger. A Helix
63957
+ * component inside is described at once, and a plain element as in the `for`
63958
+ * form: when you first point at it or focus it, or at rest where it names the
63959
+ * tooltip's `id` in its own `aria-describedby`, which a reference to the
63960
+ * element around it allows. In the
63955
63961
  * `for` form the tooltip itself is out of the accessibility tree while its
63956
63962
  * bubble is down, so you meet its words once, as the trigger's description.
63957
63963
  * A trigger whose name is already the tooltip's words, such as an icon button
@@ -72718,8 +72724,10 @@ export type CustomElementsSolidJs = {
72718
72724
  * the full list. Combobox and Select do the same. As typing narrows the list, a
72719
72725
  * screen reader hears how many commands are left, such as "3 commands".
72720
72726
  *
72721
- * **Keyboard.** Focus goes to the filter field as the palette opens, and the
72722
- * highlight moves through the commands while you type.
72727
+ * **Keyboard.** Focus goes to the filter field as the palette opens, with no
72728
+ * command highlighted, as in React Aria's Autocomplete, so Enter runs nothing
72729
+ * until you type or press Down. Typing highlights the first command left, and
72730
+ * the highlight moves through the commands while you type.
72723
72731
  *
72724
72732
  * | Key | What it does |
72725
72733
  * |---|---|
@@ -79316,6 +79324,7 @@ export type CustomElementsSolidJs = {
79316
79324
  * - `label`: The item's name. It names the item's group, and fills `{label}` in the
79317
79325
  * lightbox's `status-label`.
79318
79326
  * - `value`: The item's identifier. The root compares its `active` value against it.
79327
+ * Without one, the item is named by its place in the set, counted from 1.
79319
79328
  * - `whenSettled`: Resolves a frame after the first update, when transitions are switched on.
79320
79329
  *
79321
79330
  * **Named `whenSettled` because `settled` is taken four times over**, by
@@ -79376,7 +79385,9 @@ export type CustomElementsSolidJs = {
79376
79385
  *
79377
79386
  * A lightbox shows one item at a time and has no scrolling track, so `active`
79378
79387
  * holds the current item, as in `Tabs`. The arrow keys change the item while
79379
- * focus stays in the dialog.
79388
+ * focus stays in the dialog. `active` names an item by its `value`, and an
79389
+ * item with no `value` by its place, counted from 1, as in `Steps`, so a set
79390
+ * written without values moves and `helix-activate` says `1`, `2` and so on.
79380
79391
  *
79381
79392
  * Set `controls` for the viewer's own previous, next and close controls, named
79382
79393
  * by `previous-label`, `next-label` and `dismiss-label`, whose glyphs you can
@@ -79393,9 +79404,9 @@ export type CustomElementsSolidJs = {
79393
79404
  * `--lightbox-pan-x` and `--lightbox-pan-y`, written only while zoomed, and a
79394
79405
  * swipe moves to the next item only while the item is at its own size. With
79395
79406
  * `controls`, the viewer also draws zoom-out and zoom-in controls, for a
79396
- * pointer with no wheel and no second finger. Once a reader stops zooming, the
79397
- * live region says the new scale in the words of `zoom-status-label`, such as
79398
- * "Zoomed to 150%".
79407
+ * pointer with no wheel and no second finger. Once a reader stops zooming, and
79408
+ * at once for a key or a zoom control, the live region says the new scale in
79409
+ * the words of `zoom-status-label`, such as "Zoomed to 150%".
79399
79410
  *
79400
79411
  * Each item is a slide: a `group` with the role description in
79401
79412
  * `slide-role-label`, named by its `label` or by `slide-label`. A touch or a pen
@@ -79558,15 +79569,10 @@ export type CustomElementsSolidJs = {
79558
79569
  * - `previous() => void`: Shows the previous item. Before the first item, it shows the last when
79559
79570
  * `loop` is set.
79560
79571
  * - `toggleFullscreen() => void`: Makes the viewer fill the screen, or exits fullscreen.
79561
- * - `requestActive(next: string, cause?: string) => boolean`: Requests a new current item, and returns whether the change was applied.
79572
+ * - `requestActive(next: string, cause?: string) => boolean`: Requests a new shown item, and returns whether it moved.
79562
79573
  *
79563
- * Announces before it acts, so `preventDefault()` on the `helix-before-activate` is
79564
- * a refusal and nothing moves. Unlike a native control, nothing has moved
79565
- * by the time this runs, so refusing is simply not writing: there is
79566
- * nothing to put back. Nobody refusing means the set updates itself,
79567
- * whether or not a consumer declared `active`, a declared property being a
79568
- * seed and a correction. `cause` says why, where the family names its
79569
- * causes, and reaches the event as `detail.cause`.
79574
+ * Where `active` names nothing, it is first written with the item on
79575
+ * screen, so `helix-activate` names the item you saw as `previous`.
79570
79576
  * - `requestOpen(next: boolean) => boolean`: Requests that the element open or close, and returns whether the change
79571
79577
  * was applied.
79572
79578
  *
@@ -83412,8 +83418,9 @@ export type CustomElementsSolidJs = {
83412
83418
  * the items and written to an attribute, so a stylesheet and a badge can both
83413
83419
  * use it without counting.
83414
83420
  *
83415
- * **The feed is one `Tab` stop for its rows.** Each row takes focus itself and
83416
- * is read by its label. `ArrowDown` and `ArrowUp` move to the next and the
83421
+ * **The feed is one `Tab` stop for its rows.** It is an APG feed: the list is
83422
+ * a `feed`, busy while `loading` is set, and each row is an `article` that
83423
+ * takes focus itself and is read by its label. `ArrowDown` and `ArrowUp` move to the next and the
83417
83424
  * previous row, `Home` and `End` to the first and the last, and `PageDown` and
83418
83425
  * `PageUp` move a row on or back from anywhere inside one, as in the APG feed
83419
83426
  * pattern. The controls inside a row stay in the `Tab` order. Set `total` when
@@ -83593,7 +83600,7 @@ export type CustomElementsSolidJs = {
83593
83600
  * - `error`: Shown while `load-error` is set, under any rows there are, in place of the empty and loading lines.
83594
83601
  * - `footer`: The region below the list.
83595
83602
  * - `header`: The region above the list.
83596
- * - `list`: The list itself.
83603
+ * - `list`: The list itself, a `feed` whose rows are its articles.
83597
83604
  * - `live`: A copy of the empty, loading and error messages, in a live region that screen readers announce when they change. Visually hidden in the styled tier.
83598
83605
  * - `loading`: Shown while the feed is loading.
83599
83606
  * - `mark-all`: The control that marks everything read.
@@ -93583,8 +93590,11 @@ export type CustomElementsSolidJs = {
93583
93590
  * markup is described when you first point at it or focus it, so a screen
93584
93591
  * reader in reading mode meets it with no description until then. Where the
93585
93592
  * browser has no element references, nothing links the two, and the tooltip
93586
- * warns once on first open. The tooltip can also wrap its trigger, which
93587
- * describes a Helix component and leaves a plain element undescribed. In the
93593
+ * warns once on first open. The tooltip can also wrap its trigger. A Helix
93594
+ * component inside is described at once, and a plain element as in the `for`
93595
+ * form: when you first point at it or focus it, or at rest where it names the
93596
+ * tooltip's `id` in its own `aria-describedby`, which a reference to the
93597
+ * element around it allows. In the
93588
93598
  * `for` form the tooltip itself is out of the accessibility tree while its
93589
93599
  * bubble is down, so you meet its words once, as the trigger's description.
93590
93600
  * A trigger whose name is already the tooltip's words, such as an icon button
package/types/vue.d.ts CHANGED
@@ -8897,7 +8897,8 @@ Written by the root, which is the only thing that sees the set. */
8897
8897
  /** The item's name. It names the item's group, and fills `{label}` in the
8898
8898
  lightbox's `status-label`. */
8899
8899
  label?: (HelixHeadlessLightboxItem["label"]) | undefined;
8900
- /** The item's identifier. The root compares its `active` value against it. */
8900
+ /** The item's identifier. The root compares its `active` value against it.
8901
+ Without one, the item is named by its place in the set, counted from 1. */
8901
8902
  value?: (HelixHeadlessLightboxItem["value"]) | undefined;
8902
8903
  };
8903
8904
 
@@ -19282,7 +19283,7 @@ export interface WcToolkitVueGlobalComponents {
19282
19283
  HelixHeadlessComboboxVueProps,
19283
19284
  HelixHeadlessComboboxVueEvents
19284
19285
  >;
19285
- /** The list is a 'Listbox', which handles filtering, the empty state, the match highlight, 'aria-activedescendant', scrolling an option into view, and moving between options with the keyboard. The palette adds a dialog and a hotkey that opens it. The palette keeps no value. It is not a form control and submits nothing. Choosing an option dispatches 'helix-select' once. To remember the last command, store it yourself. An option with 'href' is a link to a page, which the browser follows once the palette has closed. The hotkey listener is on the document, so the hotkey works from anywhere on the page, including inside another control's text field, whether or not the palette is open. 'mod' means Command on a Mac and Control elsewhere, so you write one binding. With 'inline', the palette is drawn in the page with no dialog, as a search over a list that is always shown. **Pages.** A command can open a page of commands of its own, as a palette offers "Change theme" and then the themes. Give the option 'opens' with a name, and slot the page's commands as 'page:' and that name: '''html <helix-command> <helix-option value="theme" opens="theme">Change theme</helix-option> <helix-option value="dark" slot="page:theme">Dark</helix-option> <helix-option value="light" slot="page:theme">Light</helix-option> </helix-command> ''' Choosing the opener says 'helix-select' with its value, and canceling it keeps the page that is shown. The list then shows the page, named by the opener's words, and a screen reader hears those words. Backspace in an empty filter goes back, and a screen reader hears the name of the page it goes back to. 'page' says which page is shown. The filter is cleared when the palette closes, so each opening starts from the full list. Combobox and Select do the same. As typing narrows the list, a screen reader hears how many commands are left, such as "3 commands". **Keyboard.** Focus goes to the filter field as the palette opens, and the highlight moves through the commands while you type. | Key | What it does | |---|---| | 'hotkey', Command or Control with K by default | Opens the palette from anywhere on the page, or closes it. With 'inline', puts focus in its filter field. | | Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. | | Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. | | Home, End | Move the caret in the filter field. With 'home-end="list"', move the highlight to the first or the last command. | | Left, Right | Move the caret in the filter field. | | Enter | Runs the highlighted command, or follows it where it is a link, and closes the palette. On a command with 'opens', shows its page. | | Command or Control with Enter | Takes the highlighted command's 'alternate' destination, where it has one. | | Backspace | In an empty filter on a page, goes back to the page before. | | Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. | | Tab | Stays in the palette, which is modal. With 'inline', moves on through the page. | **ARIA.** The palette is a modal 'dialog' named by 'label', or with 'inline' no dialog at all. Inside it the filter field is a text field with 'aria-autocomplete="list"', 'aria-controls' on the list, and 'aria-activedescendant' on the highlighted command, as the field of React Aria's 'Autocomplete' is. The commands are a 'listbox' of 'option's. How many commands typing left, the empty text and the loading text are said in a polite live region. */
19286
+ /** The list is a 'Listbox', which handles filtering, the empty state, the match highlight, 'aria-activedescendant', scrolling an option into view, and moving between options with the keyboard. The palette adds a dialog and a hotkey that opens it. The palette keeps no value. It is not a form control and submits nothing. Choosing an option dispatches 'helix-select' once. To remember the last command, store it yourself. An option with 'href' is a link to a page, which the browser follows once the palette has closed. The hotkey listener is on the document, so the hotkey works from anywhere on the page, including inside another control's text field, whether or not the palette is open. 'mod' means Command on a Mac and Control elsewhere, so you write one binding. With 'inline', the palette is drawn in the page with no dialog, as a search over a list that is always shown. **Pages.** A command can open a page of commands of its own, as a palette offers "Change theme" and then the themes. Give the option 'opens' with a name, and slot the page's commands as 'page:' and that name: '''html <helix-command> <helix-option value="theme" opens="theme">Change theme</helix-option> <helix-option value="dark" slot="page:theme">Dark</helix-option> <helix-option value="light" slot="page:theme">Light</helix-option> </helix-command> ''' Choosing the opener says 'helix-select' with its value, and canceling it keeps the page that is shown. The list then shows the page, named by the opener's words, and a screen reader hears those words. Backspace in an empty filter goes back, and a screen reader hears the name of the page it goes back to. 'page' says which page is shown. The filter is cleared when the palette closes, so each opening starts from the full list. Combobox and Select do the same. As typing narrows the list, a screen reader hears how many commands are left, such as "3 commands". **Keyboard.** Focus goes to the filter field as the palette opens, with no command highlighted, as in React Aria's Autocomplete, so Enter runs nothing until you type or press Down. Typing highlights the first command left, and the highlight moves through the commands while you type. | Key | What it does | |---|---| | 'hotkey', Command or Control with K by default | Opens the palette from anywhere on the page, or closes it. With 'inline', puts focus in its filter field. | | Down, Up | Moves the highlight to the next or the previous command, round from the last to the first. | | Page Down, Page Up | Moves the highlight by as many commands as the list shows at once. | | Home, End | Move the caret in the filter field. With 'home-end="list"', move the highlight to the first or the last command. | | Left, Right | Move the caret in the filter field. | | Enter | Runs the highlighted command, or follows it where it is a link, and closes the palette. On a command with 'opens', shows its page. | | Command or Control with Enter | Takes the highlighted command's 'alternate' destination, where it has one. | | Backspace | In an empty filter on a page, goes back to the page before. | | Escape | Clears the filter. With the filter empty, closes the palette and puts focus back where it was. | | Tab | Stays in the palette, which is modal. With 'inline', moves on through the page. | **ARIA.** The palette is a modal 'dialog' named by 'label', or with 'inline' no dialog at all. Inside it the filter field is a text field with 'aria-autocomplete="list"', 'aria-controls' on the list, and 'aria-activedescendant' on the highlighted command, as the field of React Aria's 'Autocomplete' is. The commands are a 'listbox' of 'option's. How many commands typing left, the empty text and the loading text are said in a polite live region. */
19286
19287
  "helix-headless-command": DefineCustomElement<
19287
19288
  HelixHeadlessCommand,
19288
19289
  HelixHeadlessCommandVueProps,
@@ -19462,7 +19463,7 @@ export interface WcToolkitVueGlobalComponents {
19462
19463
  HelixHeadlessLightboxItemVueProps,
19463
19464
  HelixHeadlessLightboxItemVueEvents
19464
19465
  >;
19465
- /** The frame around content you open, such as a picture, a video frame, or a chart. The lightbox draws no content of its own. It provides the frame, the keyboard behavior, and text that states the current position in the set. The modal behavior comes from a native '<dialog>' opened with 'showModal()', which provides the top layer, a backdrop, Escape to close, and 'inert' on the rest of the document. Every way of closing goes through 'requestOpen', as in 'Dialog' and 'Drawer'. A lightbox shows one item at a time and has no scrolling track, so 'active' holds the current item, as in 'Tabs'. The arrow keys change the item while focus stays in the dialog. Set 'controls' for the viewer's own previous, next and close controls, named by 'previous-label', 'next-label' and 'dismiss-label', whose glyphs you can replace in the 'previous-icon', 'next-icon' and 'dismiss-icon' slots. Without it, compose the chrome yourself in the 'header' and 'footer' slots, with buttons that send '--previous', '--next' and '--close'. **Set 'max-zoom' to let a reader zoom into the shown item**, such as '3'. Two fingers pinch it, and so does a trackpad pinch or the wheel with Ctrl held, about the point under the pointer. A double click or a double tap zooms all the way in about the point pressed and back out, and once zoomed one pointer drags it about and the wheel moves it. '+' and '-' zoom in and out from the keyboard, and '0' puts it back. The scale and the offset are on the 'viewport' part as '--lightbox-zoom', '--lightbox-pan-x' and '--lightbox-pan-y', written only while zoomed, and a swipe moves to the next item only while the item is at its own size. With 'controls', the viewer also draws zoom-out and zoom-in controls, for a pointer with no wheel and no second finger. Once a reader stops zooming, the live region says the new scale in the words of 'zoom-status-label', such as "Zoomed to 150%". Each item is a slide: a 'group' with the role description in 'slide-role-label', named by its 'label' or by 'slide-label'. A touch or a pen swiped across the picture shows the next or the previous item, the way the line of text runs. A press on the empty area around the item closes the viewer, as a press on the backdrop does. Under 'max-zoom', a press beside the item zooms on a double press and closes nothing, and only the space outside the viewport closes the viewer. A press that dragged closes nothing. **Keyboard.** Opening moves focus to the viewer itself, which a screen reader names. | Key | What it does | |---|---| | Right, Down | Shows the next item. On a right-to-left page, Left does. While the item is zoomed, the arrows move about it instead. | | Left, Up | Shows the previous item. | | Home, End | Shows the first or the last item. | | '+', '-', '0' | Zooms in, zooms out, and puts the item back at its own size, where 'max-zoom' allows zooming. | | Tab, Shift+Tab | Moves through the controls in the viewer, from the last round to the first and from the first round to the last. | | Escape | Closes the viewer. A 'helix-before-close' listener can refuse. | A development build warns when a viewer opens with no 'label'. The chrome hides when there is no input, through 'IdleController', and comes back on a pointer move, a key press, or a focus. It stays while focus is on a control in the header or the footer, so a keyboard reader is never left on a control that has gone. 'fullscreen' uses 'FullscreenController', as 'Video' does. While the viewer is open, the page behind it does not scroll. */
19466
+ /** The frame around content you open, such as a picture, a video frame, or a chart. The lightbox draws no content of its own. It provides the frame, the keyboard behavior, and text that states the current position in the set. The modal behavior comes from a native '<dialog>' opened with 'showModal()', which provides the top layer, a backdrop, Escape to close, and 'inert' on the rest of the document. Every way of closing goes through 'requestOpen', as in 'Dialog' and 'Drawer'. A lightbox shows one item at a time and has no scrolling track, so 'active' holds the current item, as in 'Tabs'. The arrow keys change the item while focus stays in the dialog. 'active' names an item by its 'value', and an item with no 'value' by its place, counted from 1, as in 'Steps', so a set written without values moves and 'helix-activate' says '1', '2' and so on. Set 'controls' for the viewer's own previous, next and close controls, named by 'previous-label', 'next-label' and 'dismiss-label', whose glyphs you can replace in the 'previous-icon', 'next-icon' and 'dismiss-icon' slots. Without it, compose the chrome yourself in the 'header' and 'footer' slots, with buttons that send '--previous', '--next' and '--close'. **Set 'max-zoom' to let a reader zoom into the shown item**, such as '3'. Two fingers pinch it, and so does a trackpad pinch or the wheel with Ctrl held, about the point under the pointer. A double click or a double tap zooms all the way in about the point pressed and back out, and once zoomed one pointer drags it about and the wheel moves it. '+' and '-' zoom in and out from the keyboard, and '0' puts it back. The scale and the offset are on the 'viewport' part as '--lightbox-zoom', '--lightbox-pan-x' and '--lightbox-pan-y', written only while zoomed, and a swipe moves to the next item only while the item is at its own size. With 'controls', the viewer also draws zoom-out and zoom-in controls, for a pointer with no wheel and no second finger. Once a reader stops zooming, and at once for a key or a zoom control, the live region says the new scale in the words of 'zoom-status-label', such as "Zoomed to 150%". Each item is a slide: a 'group' with the role description in 'slide-role-label', named by its 'label' or by 'slide-label'. A touch or a pen swiped across the picture shows the next or the previous item, the way the line of text runs. A press on the empty area around the item closes the viewer, as a press on the backdrop does. Under 'max-zoom', a press beside the item zooms on a double press and closes nothing, and only the space outside the viewport closes the viewer. A press that dragged closes nothing. **Keyboard.** Opening moves focus to the viewer itself, which a screen reader names. | Key | What it does | |---|---| | Right, Down | Shows the next item. On a right-to-left page, Left does. While the item is zoomed, the arrows move about it instead. | | Left, Up | Shows the previous item. | | Home, End | Shows the first or the last item. | | '+', '-', '0' | Zooms in, zooms out, and puts the item back at its own size, where 'max-zoom' allows zooming. | | Tab, Shift+Tab | Moves through the controls in the viewer, from the last round to the first and from the first round to the last. | | Escape | Closes the viewer. A 'helix-before-close' listener can refuse. | A development build warns when a viewer opens with no 'label'. The chrome hides when there is no input, through 'IdleController', and comes back on a pointer move, a key press, or a focus. It stays while focus is on a control in the header or the footer, so a keyboard reader is never left on a control that has gone. 'fullscreen' uses 'FullscreenController', as 'Video' does. While the viewer is open, the page behind it does not scroll. */
19466
19467
  "helix-headless-lightbox": DefineCustomElement<
19467
19468
  HelixHeadlessLightbox,
19468
19469
  HelixHeadlessLightboxVueProps,
@@ -19612,7 +19613,7 @@ export interface WcToolkitVueGlobalComponents {
19612
19613
  HelixHeadlessNotificationVueProps,
19613
19614
  HelixHeadlessNotificationVueEvents
19614
19615
  >;
19615
- /** Notifications are slotted children. Each one is your own markup, with an avatar, a link, or a button in it. Feeds usually hold tens of items, so writing them out lets an item hold anything. The list does not virtualize. Windowing needs the list to own the data, and here you own it, so N notifications are N elements. For a feed of thousands, use a data table with a custom cell. Read state is reported to you. Marking read goes from the root to the item and from the item to you, so a canceled 'helix-read' changes nothing, and if you own 'read', nothing changes until you set it. 'unread' is derived from the items and written to an attribute, so a stylesheet and a badge can both use it without counting. **The feed is one 'Tab' stop for its rows.** Each row takes focus itself and is read by its label. 'ArrowDown' and 'ArrowUp' move to the next and the previous row, 'Home' and 'End' to the first and the last, and 'PageDown' and 'PageUp' move a row on or back from anywhere inside one, as in the APG feed pattern. The controls inside a row stay in the 'Tab' order. Set 'total' when the feed holds one page of a longer list, and each row says its place in the whole of it. **Keyboard.** | Key | What it does | |---|---| | Down, Up | On a row, moves to the next or the previous row. | | Home, End | On a row, moves to the first or the last row. | | Page Down, Page Up | From anywhere in a row, moves to the next or the previous row. | | Control+End | From anywhere in the feed, moves to the first control after it on the page. | | Control+Home | From anywhere in the feed, moves to the nearest control before it on the page. | | Tab | Moves through the controls in a row, and on out of the feed. | **A notification that arrives says so.** Unread rows added above the rows there were are counted in the live region, "1 new notification", in 'arrived-label'. Rows that arrive while 'loading' is set say nothing, so set it while a page is on its way. **'load-more' adds a button after the list** that sends 'helix-load-more', for a feed that holds one page of a longer list. Append the next page, set 'loading' while it is on its way, and take 'load-more' off once there is nothing more. While the feed is loading the button stays, so focus stays on it, and it is 'aria-disabled' and sends nothing. **'load-error' says a page could not be fetched**, such as "Could not load notifications": it shows under the rows there are, in the 'error' part, in place of the empty and loading lines, and a screen reader hears it. Clear it when you ask again. */
19616
+ /** Notifications are slotted children. Each one is your own markup, with an avatar, a link, or a button in it. Feeds usually hold tens of items, so writing them out lets an item hold anything. The list does not virtualize. Windowing needs the list to own the data, and here you own it, so N notifications are N elements. For a feed of thousands, use a data table with a custom cell. Read state is reported to you. Marking read goes from the root to the item and from the item to you, so a canceled 'helix-read' changes nothing, and if you own 'read', nothing changes until you set it. 'unread' is derived from the items and written to an attribute, so a stylesheet and a badge can both use it without counting. **The feed is one 'Tab' stop for its rows.** It is an APG feed: the list is a 'feed', busy while 'loading' is set, and each row is an 'article' that takes focus itself and is read by its label. 'ArrowDown' and 'ArrowUp' move to the next and the previous row, 'Home' and 'End' to the first and the last, and 'PageDown' and 'PageUp' move a row on or back from anywhere inside one, as in the APG feed pattern. The controls inside a row stay in the 'Tab' order. Set 'total' when the feed holds one page of a longer list, and each row says its place in the whole of it. **Keyboard.** | Key | What it does | |---|---| | Down, Up | On a row, moves to the next or the previous row. | | Home, End | On a row, moves to the first or the last row. | | Page Down, Page Up | From anywhere in a row, moves to the next or the previous row. | | Control+End | From anywhere in the feed, moves to the first control after it on the page. | | Control+Home | From anywhere in the feed, moves to the nearest control before it on the page. | | Tab | Moves through the controls in a row, and on out of the feed. | **A notification that arrives says so.** Unread rows added above the rows there were are counted in the live region, "1 new notification", in 'arrived-label'. Rows that arrive while 'loading' is set say nothing, so set it while a page is on its way. **'load-more' adds a button after the list** that sends 'helix-load-more', for a feed that holds one page of a longer list. Append the next page, set 'loading' while it is on its way, and take 'load-more' off once there is nothing more. While the feed is loading the button stays, so focus stays on it, and it is 'aria-disabled' and sends nothing. **'load-error' says a page could not be fetched**, such as "Could not load notifications": it shows under the rows there are, in the 'error' part, in place of the empty and loading lines, and a screen reader hears it. Clear it when you ask again. */
19616
19617
  "helix-headless-notifications": DefineCustomElement<
19617
19618
  HelixHeadlessNotifications,
19618
19619
  HelixHeadlessNotificationsVueProps,
@@ -19936,7 +19937,7 @@ export interface WcToolkitVueGlobalComponents {
19936
19937
  HelixHeadlessToolbarVueProps,
19937
19938
  HelixHeadlessToolbarVueEvents
19938
19939
  >;
19939
- /** The trigger stays your own element. The bubble renders in the top layer through the popover API, so an ancestor with 'overflow: hidden' does not clip it and no 'z-index' is needed. 'FloatingController' positions it and flips it to another side when the preferred side does not fit. **Place the tooltip beside its trigger, name the trigger with 'for', and name the tooltip in the trigger's 'aria-describedby'.** The description is then in your own markup, so it is in the server's HTML and in the accessibility tree at rest, in every browser, before anyone points at the trigger or focuses it: '''html <helix-headless-button aria-describedby="save-tip" id="save">Save</helix-headless-button> <helix-headless-tooltip content="Save your work" for="save" id="save-tip"></helix-headless-tooltip> ''' Without the attribute, the tooltip links itself through an element reference on the control that takes focus, and it never writes into your markup before you act, so hydration stays intact. A trigger that is a Helix component is described at once, inside its own shadow root. A plain element in your markup is described when you first point at it or focus it, so a screen reader in reading mode meets it with no description until then. Where the browser has no element references, nothing links the two, and the tooltip warns once on first open. The tooltip can also wrap its trigger, which describes a Helix component and leaves a plain element undescribed. In the 'for' form the tooltip itself is out of the accessibility tree while its bubble is down, so you meet its words once, as the trigger's description. A trigger whose name is already the tooltip's words, such as an icon button named Settings under a tooltip reading Settings, is not described by them again. The tooltip shows on hover and on focus. It hides on pointer leave, on blur, on Escape, and when the trigger is activated. The pointer can move from the trigger onto the bubble and the bubble stays, unless you set 'hoverable="false"'. 'delay' is how long the pointer rests before it shows, and 'delay-out' how long it stays once the pointer leaves. Once one tooltip is showing, moving to another trigger shows its tooltip with no 'delay', and the first one hides. The same holds for 'skip-delay' milliseconds after a tooltip hides, 300 unless you set it. 'show-on="focus"' shows the tooltip on keyboard focus only, for a hint a pointer does not need. */
19940
+ /** The trigger stays your own element. The bubble renders in the top layer through the popover API, so an ancestor with 'overflow: hidden' does not clip it and no 'z-index' is needed. 'FloatingController' positions it and flips it to another side when the preferred side does not fit. **Place the tooltip beside its trigger, name the trigger with 'for', and name the tooltip in the trigger's 'aria-describedby'.** The description is then in your own markup, so it is in the server's HTML and in the accessibility tree at rest, in every browser, before anyone points at the trigger or focuses it: '''html <helix-headless-button aria-describedby="save-tip" id="save">Save</helix-headless-button> <helix-headless-tooltip content="Save your work" for="save" id="save-tip"></helix-headless-tooltip> ''' Without the attribute, the tooltip links itself through an element reference on the control that takes focus, and it never writes into your markup before you act, so hydration stays intact. A trigger that is a Helix component is described at once, inside its own shadow root. A plain element in your markup is described when you first point at it or focus it, so a screen reader in reading mode meets it with no description until then. Where the browser has no element references, nothing links the two, and the tooltip warns once on first open. The tooltip can also wrap its trigger. A Helix component inside is described at once, and a plain element as in the 'for' form: when you first point at it or focus it, or at rest where it names the tooltip's 'id' in its own 'aria-describedby', which a reference to the element around it allows. In the 'for' form the tooltip itself is out of the accessibility tree while its bubble is down, so you meet its words once, as the trigger's description. A trigger whose name is already the tooltip's words, such as an icon button named Settings under a tooltip reading Settings, is not described by them again. The tooltip shows on hover and on focus. It hides on pointer leave, on blur, on Escape, and when the trigger is activated. The pointer can move from the trigger onto the bubble and the bubble stays, unless you set 'hoverable="false"'. 'delay' is how long the pointer rests before it shows, and 'delay-out' how long it stays once the pointer leaves. Once one tooltip is showing, moving to another trigger shows its tooltip with no 'delay', and the first one hides. The same holds for 'skip-delay' milliseconds after a tooltip hides, 300 unless you set it. 'show-on="focus"' shows the tooltip on keyboard focus only, for a hint a pointer does not need. */
19940
19941
  "helix-headless-tooltip": DefineCustomElement<
19941
19942
  HelixHeadlessTooltip,
19942
19943
  HelixHeadlessTooltipVueProps,