@aurodesignsystem-dev/auro-formkit 0.0.0-pr1503.3 → 0.0.0-pr1503.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/components/bibtemplate/dist/index.js +1 -1
  2. package/components/bibtemplate/dist/registered.js +1 -1
  3. package/components/checkbox/demo/accessibility.md +1 -1
  4. package/components/checkbox/demo/customize.html +1 -2
  5. package/components/checkbox/demo/customize.min.js +23 -8
  6. package/components/checkbox/demo/getting-started.min.js +23 -8
  7. package/components/checkbox/demo/index.min.js +23 -8
  8. package/components/checkbox/dist/index.js +23 -8
  9. package/components/checkbox/dist/registered.js +23 -8
  10. package/components/combobox/README.md +1 -1
  11. package/components/combobox/demo/accessibility.md +1 -1
  12. package/components/combobox/demo/api.md +2 -2
  13. package/components/combobox/demo/customize.html +1 -2
  14. package/components/combobox/demo/customize.md +166 -142
  15. package/components/combobox/demo/customize.min.js +2515 -2316
  16. package/components/combobox/demo/getting-started.min.js +2515 -2312
  17. package/components/combobox/demo/index.md +2 -1
  18. package/components/combobox/demo/index.min.js +2515 -2312
  19. package/components/combobox/demo/keyboard-behavior.md +3 -146
  20. package/components/combobox/demo/readme.md +1 -1
  21. package/components/combobox/demo/why-combobox.md +2 -2
  22. package/components/combobox/dist/auro-combobox.d.ts +49 -15
  23. package/components/combobox/dist/index.js +1462 -753
  24. package/components/combobox/dist/registered.js +1462 -753
  25. package/components/counter/demo/customize.min.js +188 -244
  26. package/components/counter/demo/index.min.js +188 -244
  27. package/components/counter/dist/auro-counter.d.ts +0 -8
  28. package/components/counter/dist/index.js +188 -244
  29. package/components/counter/dist/registered.js +188 -244
  30. package/components/datepicker/demo/accessibility.md +20 -10
  31. package/components/datepicker/demo/api.md +65 -62
  32. package/components/datepicker/demo/customize.md +180 -40
  33. package/components/datepicker/demo/customize.min.js +1690 -777
  34. package/components/datepicker/demo/getting-started.md +118 -2
  35. package/components/datepicker/demo/index.min.js +1690 -759
  36. package/components/datepicker/demo/keyboard-behavior.md +3 -3
  37. package/components/datepicker/demo/voiceover.md +4 -4
  38. package/components/datepicker/demo/why-datepicker.md +2 -2
  39. package/components/datepicker/dist/{src/auro-calendar-cell.d.ts → auro-calendar-cell.d.ts} +48 -3
  40. package/components/datepicker/dist/{src/auro-calendar.d.ts → auro-calendar.d.ts} +188 -10
  41. package/components/datepicker/dist/{src/auro-datepicker.d.ts → auro-datepicker.d.ts} +89 -6
  42. package/components/datepicker/dist/blackoutUtils.d.ts +43 -0
  43. package/components/datepicker/dist/index.js +1690 -759
  44. package/components/datepicker/dist/registered.js +1690 -759
  45. package/components/dropdown/demo/customize.html +3 -0
  46. package/components/dropdown/demo/customize.min.js +142 -208
  47. package/components/dropdown/demo/getting-started.min.js +131 -207
  48. package/components/dropdown/demo/index.min.js +131 -207
  49. package/components/dropdown/dist/auro-dropdown.d.ts +17 -1
  50. package/components/dropdown/dist/index.js +131 -207
  51. package/components/dropdown/dist/registered.js +131 -207
  52. package/components/form/demo/api.md +3 -3
  53. package/components/form/demo/customize.html +6 -6
  54. package/components/form/demo/customize.md +535 -135
  55. package/components/form/demo/customize.min.js +6307 -4378
  56. package/components/form/demo/getting-started.md +344 -96
  57. package/components/form/demo/getting-started.min.js +6255 -4378
  58. package/components/form/demo/index.min.js +6206 -4378
  59. package/components/form/demo/registerDemoDeps.min.js +5827 -4333
  60. package/components/form/dist/auro-form.d.ts +128 -10
  61. package/components/form/dist/index.js +377 -43
  62. package/components/form/dist/registered.js +377 -43
  63. package/components/input/demo/accessibility.md +1 -1
  64. package/components/input/demo/api.md +58 -57
  65. package/components/input/demo/customize.html +1 -2
  66. package/components/input/demo/customize.md +62 -61
  67. package/components/input/demo/customize.min.js +396 -275
  68. package/components/input/demo/getting-started.min.js +396 -275
  69. package/components/input/demo/index.min.js +396 -275
  70. package/components/input/dist/auro-input.d.ts +1 -1
  71. package/components/input/dist/base-input.d.ts +60 -81
  72. package/components/input/dist/index.js +409 -276
  73. package/components/input/dist/registered.js +396 -275
  74. package/components/input/dist/utilities.d.ts +10 -1
  75. package/components/menu/demo/accessibility.md +9 -4
  76. package/components/menu/demo/api.md +48 -45
  77. package/components/menu/demo/css-only.md +26 -19
  78. package/components/menu/demo/customize.md +307 -75
  79. package/components/menu/demo/design.md +1 -1
  80. package/components/menu/demo/getting-started.md +144 -7
  81. package/components/menu/demo/index.min.js +961 -1341
  82. package/components/menu/demo/keyboard-behavior.md +83 -4
  83. package/components/menu/demo/voiceover.md +21 -14
  84. package/components/menu/demo/why-menu.md +8 -9
  85. package/components/menu/dist/auro-menu-utils.d.ts +19 -0
  86. package/components/menu/dist/auro-menu.d.ts +97 -116
  87. package/components/menu/dist/auro-menuoption.d.ts +39 -133
  88. package/components/menu/dist/index.js +823 -1309
  89. package/components/menu/dist/registered.js +835 -1309
  90. package/components/radio/demo/accessibility.md +1 -1
  91. package/components/radio/demo/customize.min.js +23 -8
  92. package/components/radio/demo/getting-started.min.js +23 -8
  93. package/components/radio/demo/index.min.js +23 -8
  94. package/components/radio/dist/index.js +23 -8
  95. package/components/radio/dist/registered.js +23 -8
  96. package/components/select/demo/accessibility.md +6 -1
  97. package/components/select/demo/api.md +3 -2
  98. package/components/select/demo/customize.html +1 -2
  99. package/components/select/demo/customize.md +210 -5
  100. package/components/select/demo/customize.min.js +1613 -1854
  101. package/components/select/demo/design.md +10 -10
  102. package/components/select/demo/getting-started.md +1 -1
  103. package/components/select/demo/getting-started.min.js +1617 -1903
  104. package/components/select/demo/index.md +2 -2
  105. package/components/select/demo/index.min.js +1613 -1854
  106. package/components/select/demo/keyboard-behavior.md +81 -54
  107. package/components/select/demo/voiceover.md +28 -15
  108. package/components/select/dist/auro-select.d.ts +70 -12
  109. package/components/select/dist/index.js +580 -315
  110. package/components/select/dist/registered.js +580 -315
  111. package/components/select/dist/selectUtils.d.ts +24 -0
  112. package/custom-elements.json +8071 -7919
  113. package/package.json +7 -3
  114. package/components/checkbox/demo/customize.js +0 -22
  115. package/components/checkbox/demo/demo-support.js +0 -1
  116. package/components/checkbox/demo/getting-started.js +0 -22
  117. package/components/checkbox/demo/index.js +0 -8
  118. package/components/checkbox/demo/styles.scss +0 -1
  119. package/components/combobox/demo/customize.js +0 -24
  120. package/components/combobox/demo/demo-support.js +0 -1
  121. package/components/combobox/demo/getting-started.js +0 -21
  122. package/components/combobox/demo/index.js +0 -23
  123. package/components/combobox/demo/styles.scss +0 -1
  124. package/components/counter/demo/customize.js +0 -21
  125. package/components/counter/demo/demo-support.js +0 -1
  126. package/components/counter/demo/index.js +0 -21
  127. package/components/counter/demo/styles.scss +0 -1
  128. package/components/datepicker/demo/customize.js +0 -19
  129. package/components/datepicker/demo/demo-support.js +0 -1
  130. package/components/datepicker/demo/index.js +0 -23
  131. package/components/datepicker/demo/styles.scss +0 -1
  132. package/components/dropdown/demo/customize.js +0 -9
  133. package/components/dropdown/demo/demo-support.js +0 -1
  134. package/components/dropdown/demo/getting-started.js +0 -9
  135. package/components/dropdown/demo/index.js +0 -16
  136. package/components/dropdown/demo/styles.scss +0 -1
  137. package/components/form/demo/customize.js +0 -9
  138. package/components/form/demo/demo-support.js +0 -1
  139. package/components/form/demo/getting-started.js +0 -9
  140. package/components/form/demo/index.js +0 -5
  141. package/components/form/demo/registerDemoDeps.js +0 -23
  142. package/components/form/demo/styles.scss +0 -1
  143. package/components/input/demo/customize.js +0 -25
  144. package/components/input/demo/demo-support.js +0 -1
  145. package/components/input/demo/getting-started.js +0 -8
  146. package/components/input/demo/index.js +0 -8
  147. package/components/input/demo/styles.css +0 -974
  148. package/components/input/demo/styles.scss +0 -1
  149. package/components/menu/demo/demo-support.js +0 -1
  150. package/components/menu/demo/index.js +0 -25
  151. package/components/menu/demo/styles.scss +0 -1
  152. package/components/menu/dist/auro-menu.context.d.ts +0 -238
  153. package/components/radio/demo/customize.js +0 -22
  154. package/components/radio/demo/demo-support.js +0 -1
  155. package/components/radio/demo/getting-started.js +0 -24
  156. package/components/radio/demo/index.js +0 -8
  157. package/components/radio/demo/styles.scss +0 -1
  158. package/components/select/demo/customize.js +0 -11
  159. package/components/select/demo/demo-support.js +0 -1
  160. package/components/select/demo/getting-started.js +0 -26
  161. package/components/select/demo/index.js +0 -11
  162. package/components/select/demo/styles.scss +0 -1
  163. /package/components/counter/dist/styles/{counter-wrapper-color-css.d.ts → counter-group-color-css.d.ts} +0 -0
  164. /package/components/datepicker/dist/{src/auro-calendar-month.d.ts → auro-calendar-month.d.ts} +0 -0
  165. /package/components/datepicker/dist/{src/buttonVersion.d.ts → buttonVersion.d.ts} +0 -0
  166. /package/components/datepicker/dist/{src/datepickerKeyboardStrategy.d.ts → datepickerKeyboardStrategy.d.ts} +0 -0
  167. /package/components/datepicker/dist/{src/iconVersion.d.ts → iconVersion.d.ts} +0 -0
  168. /package/components/datepicker/dist/{src/index.d.ts → index.d.ts} +0 -0
  169. /package/components/datepicker/dist/{src/popoverVersion.d.ts → popoverVersion.d.ts} +0 -0
  170. /package/components/datepicker/dist/{src/styles → styles}/classic/color-css.d.ts +0 -0
  171. /package/components/datepicker/dist/{src/styles → styles}/classic/style-css.d.ts +0 -0
  172. /package/components/datepicker/dist/{src/styles → styles}/color-calendar-css.d.ts +0 -0
  173. /package/components/datepicker/dist/{src/styles → styles}/color-cell-css.d.ts +0 -0
  174. /package/components/datepicker/dist/{src/styles → styles}/color-css.d.ts +0 -0
  175. /package/components/datepicker/dist/{src/styles → styles}/color-month-css.d.ts +0 -0
  176. /package/components/datepicker/dist/{src/styles → styles}/shapeSize-css.d.ts +0 -0
  177. /package/components/datepicker/dist/{src/styles → styles}/snowflake/color-css.d.ts +0 -0
  178. /package/components/datepicker/dist/{src/styles → styles}/snowflake/style-css.d.ts +0 -0
  179. /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-cell-css.d.ts +0 -0
  180. /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-css.d.ts +0 -0
  181. /package/components/datepicker/dist/{src/styles → styles}/style-auro-calendar-month-css.d.ts +0 -0
  182. /package/components/datepicker/dist/{src/styles → styles}/style-css.d.ts +0 -0
  183. /package/components/datepicker/dist/{src/styles → styles}/tokens-css.d.ts +0 -0
  184. /package/components/datepicker/dist/{src/utilities.d.ts → utilities.d.ts} +0 -0
  185. /package/components/datepicker/dist/{src/utilitiesCalendar.d.ts → utilitiesCalendar.d.ts} +0 -0
  186. /package/components/datepicker/dist/{src/utilitiesCalendarRender.d.ts → utilitiesCalendarRender.d.ts} +0 -0
  187. /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/day.d.ts +0 -0
  188. /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker-calendar.d.ts +0 -0
  189. /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker-cell.d.ts +0 -0
  190. /package/components/datepicker/dist/{src/vendor → vendor}/wc-range-datepicker/range-datepicker.d.ts +0 -0
@@ -7,11 +7,90 @@
7
7
  <auro-header level="2" id="keyEvents">Key Events</auro-header>
8
8
  <!-- AURO-GENERATED-CONTENT:START (FILE:src=./../docs/partials/keyEvents.md) -->
9
9
  <!-- The below content is automatically added from ./../docs/partials/keyEvents.md -->
10
- <!-- auro-menu does not implement direct keyboard event handling. -->
11
- <!-- Keyboard navigation is delegated to parent components (auro-select, auro-combobox) via their keyboard strategy files. -->
12
10
  <div class="note">
13
- <p><strong>Note:</strong> The <code>&lt;auro-menu&gt;</code> component does not handle keyboard events directly. Keyboard navigation is managed by the parent component (e.g., <code>&lt;auro-select&gt;</code>, <code>&lt;auro-combobox&gt;</code>) through their keyboard strategy classes, which call menu methods such as <code>navigateOptions()</code>, <code>makeSelection()</code>, and <code>updateActiveOption()</code>.</p>
14
- </div>
11
+ <p><strong>Note:</strong> <code>&lt;auro-menu&gt;</code> registers a <code>keydown</code> listener on its host. By default the menu is not focusable no <code>tabindex</code> on the host, and menuoptions are <code>tabindex="-1"</code> so the listener does not fire on its own. It fires whenever a <code>keydown</code> reaches the host, which happens in any of the following ways:</p>
12
+ <ul>
13
+ <li>A wrapping component focuses something inside the menu subtree and the event bubbles up to the host. In the standard integrations (<code>&lt;auro-select&gt;</code>, <code>&lt;auro-combobox&gt;</code>), keyboard behavior is primarily parent-managed rather than bubble-driven: focus stays on the parent's trigger/input, and the parent captures keys there and drives the menu directly via its public <code>navigateOptions()</code> / <code>updateActiveOption()</code> methods and the menu's internal <code>makeSelection()</code> routine (<code>@private</code>, not part of the public menu API).</li>
14
+ <li>A wrapping component dispatches or reroutes a <code>KeyboardEvent</code> at the menu programmatically (for example, <code>menu.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))</code>).</li>
15
+ <li>The author makes the host focusable (for example, by adding <code>tabindex="0"</code> to the <code>&lt;auro-menu&gt;</code> element) and focuses it. The host already has <code>role="listbox"</code>, so this yields a bare, focusable listbox that responds to the keys in the table below. For full combobox semantics use <code>&lt;auro-select&gt;</code> or <code>&lt;auro-combobox&gt;</code>, or replicate their <code>aria-activedescendant</code> wiring from a separate trigger.</li>
16
+ </ul>
17
+ <p>Keys not listed below (<code>Home</code>, <code>End</code>, <code>Escape</code>, type-ahead) are handled by the parent — see the <code>&lt;auro-select&gt;</code> and <code>&lt;auro-combobox&gt;</code> keyboard behavior docs. An "interactive option" is one that is not <code>disabled</code>, <code>hidden</code>, or <code>static</code> — these are always skipped during navigation and selection, along with <code>&lt;hr&gt;</code> dividers.</p>
18
+ </div>
19
+ <table>
20
+ <thead>
21
+ <tr>
22
+ <th>Key</th>
23
+ <th>Current State</th>
24
+ <th>Behavior</th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <tr>
29
+ <td rowspan="5">ArrowDown</td>
30
+ <td>No option is active</td>
31
+ <td>The first interactive option becomes active.</td>
32
+ </tr>
33
+ <tr>
34
+ <td>An option is active, followed by interactive options</td>
35
+ <td>Advances the active option to the next interactive option.</td>
36
+ </tr>
37
+ <tr>
38
+ <td>The last interactive option is active</td>
39
+ <td>Wraps to the first interactive option.</td>
40
+ </tr>
41
+ <tr>
42
+ <td>Menu has no options or all options are non-interactive</td>
43
+ <td>No option becomes active; no <code>auroMenu-activatedOption</code> event fires.</td>
44
+ </tr>
45
+ <tr>
46
+ <td>Menu is in <code>loading</code> state</td>
47
+ <td>The rendered loading placeholder is inert (marked <code>disabled</code>) and is not part of <code>items</code>, so it cannot become active.</td>
48
+ </tr>
49
+ <tr>
50
+ <td rowspan="4">ArrowUp</td>
51
+ <td>No option is active</td>
52
+ <td>The last interactive option becomes active.</td>
53
+ </tr>
54
+ <tr>
55
+ <td>An option is active, preceded by interactive options</td>
56
+ <td>Advances the active option to the previous interactive option.</td>
57
+ </tr>
58
+ <tr>
59
+ <td>The first interactive option is active</td>
60
+ <td>Wraps to the last interactive option.</td>
61
+ </tr>
62
+ <tr>
63
+ <td>Menu has no options or all options are non-interactive</td>
64
+ <td>No option becomes active.</td>
65
+ </tr>
66
+ <tr>
67
+ <td rowspan="4">Enter</td>
68
+ <td>Single-select, active option is not currently selected</td>
69
+ <td>The active option is selected. Any previous selection is cleared. <code>auroMenu-selectedOption</code> fires.</td>
70
+ </tr>
71
+ <tr>
72
+ <td>Single-select, active option is already selected</td>
73
+ <td>No selection change, but <code>auroMenu-selectedOption</code> still fires so the parent can react (for example, close the dropdown).</td>
74
+ </tr>
75
+ <tr>
76
+ <td>Multi-select</td>
77
+ <td>The active option toggles selected. Other selections are preserved.</td>
78
+ </tr>
79
+ <tr>
80
+ <td>Active option is disabled, hidden, or static</td>
81
+ <td>Selection is a no-op.</td>
82
+ </tr>
83
+ <tr>
84
+ <td rowspan="2">Tab</td>
85
+ <td>An option is active</td>
86
+ <td>The active option is selected (same behavior as <code>Enter</code>).<div class="note"><strong>Note:</strong> <code>Tab</code> does not <code>preventDefault</code>, so focus continues to the next element in the tabindex sequence after selection.</div></td>
87
+ </tr>
88
+ <tr>
89
+ <td>No option is active</td>
90
+ <td>Focus moves to the next tabbable element; no selection change.</td>
91
+ </tr>
92
+ </tbody>
93
+ </table>
15
94
  <!-- AURO-GENERATED-CONTENT:END -->
16
95
  </div>
17
96
  </div>
@@ -1,33 +1,40 @@
1
1
  <auro-header level="1" id="overview">Menu - VoiceOver Behavior</auro-header>
2
2
  <p>This page documents the VoiceOver experience when using the <code>&lt;auro-menu&gt;</code> component. It covers announcements and interactions for menu navigation and option selection.</p>
3
+ <div class="note"><strong>Note:</strong> In the standard integrations (<code>&lt;auro-select&gt;</code>, <code>&lt;auro-combobox&gt;</code>), keyboard focus stays on the parent trigger/input — it does <strong>not</strong> move into the menu. The parent captures keys and drives the menu, and the active option is announced via <code>aria-activedescendant</code> on the trigger rather than by moving DOM focus between options. The focus-on-the-menu behavior described alongside the standalone case below only applies when an author makes <code>&lt;auro-menu&gt;</code> itself focusable (for example, <code>tabindex="0"</code>).</p>
3
4
  <auro-header level="2" id="voiceOverInteractiveAnnouncements">Interactive Announcements</auro-header>
4
5
  <auro-header level="3" id="voiceOverMenuContainer">Menu Container</auro-header>
5
- <p>When focus enters the menu, VoiceOver announces:</p>
6
+ <p>When the listbox is exposed — the parent's dropdown opens, or a standalone focusable menu receives focus — VoiceOver announces:</p>
6
7
  <ol>
7
- <li><strong>Role:</strong> <em>"list box"</em></li>
8
+ <li><strong>Role:</strong> <em>"list box"</em> — set on the root <code>&lt;auro-menu&gt;</code>; nested menus use <code>role="group"</code> with <code>aria-label="submenu"</code>.</li>
8
9
  <li><strong>Item count:</strong> The number of visible options (e.g., <em>"5 items"</em>)</li>
10
+ <li><strong>Multi-select:</strong> When <code>multiSelect</code> is set on the root menu, <code>aria-multiselectable="true"</code> is exposed so VoiceOver announces the listbox as multi-selectable.</li>
11
+ <li><strong>Loading:</strong> While <code>loading</code> is set, <code>aria-busy="true"</code> is exposed so VoiceOver signals that the option set is not yet stable.</li>
9
12
  </ol>
10
13
  <auro-header level="3" id="voiceOverMenuOptions">Menu Options</auro-header>
11
- <p>Each <code>auro-menuoption</code> announces the following when focused:</p>
14
+ <p>Each <code>auro-menuoption</code> announces the following when the parent field points at it (via <code>aria-activedescendant</code>) or when the user reads through the listbox:</p>
12
15
  <ol>
13
16
  <li><strong>Label:</strong> The option's text content</li>
14
17
  <li><strong>Role:</strong> <em>"option"</em></li>
15
- <li><strong>Position:</strong> Position in the list (e.g., <em>"3 of 5"</em>)</li>
16
- <li><strong>Selected state:</strong> <em>"selected"</em> if the option is currently selected</li>
17
- <li><strong>Disabled state:</strong> <em>"dimmed"</em> if the option is disabled</li>
18
- </ol>
18
+ <li><strong>Position:</strong> Position in the list (e.g., <em>"3 of 5"</em>) — when the menu is used inside <code>&lt;auro-select&gt;</code> (or another host that stamps them), each option receives <code>aria-setsize</code> and <code>aria-posinset</code>. Standalone <code>&lt;auro-menu&gt;</code> does not set these attributes itself; positional announcements outside a select/combobox host rely on VoiceOver's own listbox item count.</li>
19
+ <li><strong>Selected state:</strong> <em>"selected"</em> if <code>aria-selected="true"</code> is set on the option</li>
20
+ <li><strong>Disabled state:</strong> <em>"dimmed"</em> if <code>aria-disabled="true"</code> is set on the option</li>
21
+ </ol>
22
+ <div class="note"><strong>Note:</strong> <code>&lt;auro-menuoption&gt;</code> is not directly focusable — <code>tabindex="-1"</code> keeps it out of the tab order. In a select or combobox context, focus stays on the parent trigger and the active option is pointed at via <code>aria-activedescendant</code> (using <code>ariaActiveDescendantElement</code> to cross the shadow-root boundary).</div>
19
23
  <auro-header level="3" id="voiceOverSelection">Selection</auro-header>
20
- <p>When an option is selected via Enter or Space:</p>
24
+ <p>In a select or combobox context, the parent captures Enter (and Tab) on its trigger/input and commits the active option through the menu; the menu itself does not receive the key. When the selection is committed:</p>
21
25
  <ul>
22
26
  <li>VoiceOver announces the option label followed by <em>"selected"</em></li>
23
27
  <li>In multi-select mode, previously selected options remain selected and their state is preserved</li>
24
- </ul>
28
+ </ul>
29
+ <p>A standalone focusable menu (see the note at the top of this page) handles Enter and Tab on its own host, producing the same selection announcement.</p>
25
30
  <auro-header level="2" id="voiceOverWorkflow">Navigation Workflow</auro-header>
31
+ <p>In the standard select/combobox integrations, focus remains on the parent trigger/input throughout — the menu is a visually presented listbox the parent points into, not a place focus travels to:</p>
26
32
  <ol>
27
- <li><strong>Enter the menu:</strong> Focus moves into the listbox; VoiceOver announces role and item count</li>
28
- <li><strong>Navigate options:</strong> Use Arrow Down/Up keys; VoiceOver announces each option's label, role, and position</li>
29
- <li><strong>Select an option:</strong> Press Enter or Space; VoiceOver confirms the selection</li>
30
- <li><strong>Exit:</strong> Tab out of the menu or press Escape (when used within a dropdown context)</li>
31
- </ol>
33
+ <li><strong>Open the listbox:</strong> Activating the trigger (or typing in a combobox) exposes the menu; VoiceOver announces the listbox role and item count</li>
34
+ <li><strong>Navigate options:</strong> Arrow Down/Up keys pressed on the trigger move the active option; <code>aria-activedescendant</code> updates and VoiceOver announces each option's label, role, and position</li>
35
+ <li><strong>Select an option:</strong> Enter (captured by the parent) commits the active option; VoiceOver confirms the selection</li>
36
+ <li><strong>Exit:</strong> Escape and Tab are handled by the parent Escape closes the listbox, and Tab commits the active option before moving focus to the next element in the tab sequence</li>
37
+ </ol>
38
+ <p>A standalone focusable menu follows the same active-option model, except focus is on the menu host and the menu handles Arrow, Enter, and Tab directly. See the menu's key events documentation for the full standalone key table.</p>
32
39
  <auro-header level="2" id="voiceOverNestedMenus">Nested Menus</auro-header>
33
40
  <p>When a nested <code>auro-menu</code> is encountered, VoiceOver announces a new listbox context. Each nested menu maintains its own option count and position tracking.</p>
@@ -4,7 +4,7 @@
4
4
  <p>Custom list implementations often fail to provide correct ARIA semantics, keyboard navigation, or screen reader announcements.</p>
5
5
  <p><code>auro-menu</code> provides:</p>
6
6
  <ul>
7
- <li><strong>Keyboard navigation</strong> — Arrow keys move between options, Enter selects, Escape cancels, Home/End jump to the first and last options.</li>
7
+ <li><strong>Keyboard navigation</strong> — Arrow Up/Down move the active option; Enter selects it; Tab selects and moves focus out of the menu.</li>
8
8
  <li><strong>Active option tracking</strong> — The currently highlighted option is tracked programmatically, enabling <code>aria-activedescendant</code> patterns in parent components like <code>auro-select</code> and <code>auro-combobox</code>.</li>
9
9
  <li><strong>Multi-select semantics</strong> — When <code>multiSelect</code> is enabled, <code>aria-multiselectable</code> is set on the menu.</li>
10
10
  <li><strong>Loading state</strong> — <code>aria-busy</code> is set during loading, with customizable loading icon and text slots.</li>
@@ -24,15 +24,14 @@
24
24
  <ul>
25
25
  <li>Checkmark indicators for each selected option</li>
26
26
  <li>A <code>value</code> that returns a JSON-stringified array of selections</li>
27
- <li><code>allowDeselect</code> to toggle selections off</li>
28
- <li><code>selectAllMatchingOptions</code> for bulk selection operations</li>
29
- <li><code>clearSelection()</code> and <code>reset()</code> methods for programmatic control</li>
27
+ <li>Click-to-toggle behavior that deselects an already-selected option</li>
28
+ <li><code>reset()</code> method for programmatic control</li>
30
29
  </ul>
31
30
  <auro-header level="2" id="searchAndFiltering">Search and filtering</auro-header>
32
31
  <p>Native menus have no concept of filtering or highlighting matched text.</p>
33
32
  <p><code>auro-menu</code> supports:</p>
34
33
  <ul>
35
- <li><code>matchWord</code> to highlight matching portions of option text as the user types (used by <code>auro-combobox</code> for real-time filtering)</li>
34
+ <li><auro-hyperlink href="customize#matchWord"><code>matchWord</code></auro-hyperlink> to highlight matching portions of option text as the user types (used by <code>auro-combobox</code> for real-time filtering)</li>
36
35
  <li>Programmatic <code>navigateOptions(direction)</code> for keyboard-driven traversal</li>
37
36
  </ul>
38
37
  <auro-header level="2" id="loadingState">Loading state</auro-header>
@@ -88,7 +87,7 @@
88
87
  <tr>
89
88
  <td>Keyboard navigation</td>
90
89
  <td>Browser-dependent</td>
91
- <td>Full arrow/Enter/Escape/Home/End</td>
90
+ <td>Arrow Up/Down, Enter, Tab</td>
92
91
  </tr>
93
92
  <tr>
94
93
  <td>Composable primitive</td>
@@ -96,9 +95,9 @@
96
95
  <td>Foundation for select and combobox</td>
97
96
  </tr>
98
97
  <tr>
99
- <td>Deselect support</td>
100
- <td>No</td>
101
- <td><code>allowDeselect</code> attribute</td>
98
+ <td>Multi-select deselect</td>
99
+ <td>Ctrl+click list box</td>
100
+ <td>Click-to-toggle in multi-select</td>
102
101
  </tr>
103
102
  </tbody>
104
103
  </table>
@@ -10,6 +10,15 @@
10
10
  * or if the value cannot be parsed into an array from a JSON string.
11
11
  */
12
12
  export function arrayConverter(value: any): any[] | undefined;
13
+ /**
14
+ * Serializes a multi-select value array back into the String `value` property.
15
+ * An empty (or missing) array collapses to `undefined` so an emptied selection
16
+ * clears `value` rather than reflecting a `"[]"` attribute.
17
+ * @private
18
+ * @param {Array<string>|undefined} values - The selected values.
19
+ * @returns {string|undefined} JSON string of the values, or undefined when empty.
20
+ */
21
+ export function serializeMultiSelectValue(values: Array<string> | undefined): string | undefined;
13
22
  /**
14
23
  * Compare two arrays for equality.
15
24
  * @private
@@ -25,6 +34,16 @@ export function arraysAreEqual(arr1: any[], arr2: any[]): boolean;
25
34
  * @returns {boolean} True if option is interactive.
26
35
  */
27
36
  export function isOptionInteractive(option: HTMLElement): boolean;
37
+ /**
38
+ * Validates if an option may be selected by matching a programmatic value.
39
+ * Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
40
+ * `hidden` as its type-ahead filter, so a filtered-out option is still a
41
+ * valid programmatic selection. Only disabled and static options — which are
42
+ * never selectable — are rejected.
43
+ * @param {HTMLElement} option - The option to check.
44
+ * @returns {boolean} True if option can be selected by value.
45
+ */
46
+ export function isSelectableByValue(option: HTMLElement): boolean;
28
47
  /**
29
48
  * Helper method to dispatch custom events.
30
49
  * @param {HTMLElement} element - Element to dispatch event from.
@@ -6,7 +6,6 @@
6
6
  * @event {CustomEvent<any>} auroMenu-customEventFired - Notifies that a custom event has been fired.
7
7
  * @event {CustomEvent<{ loading: boolean; hasLoadingPlaceholder: boolean; }>} auroMenu-loadingChange - Notifies when the loading attribute is changed.
8
8
  * @event {CustomEvent<any>} auroMenu-selectValueFailure - Notifies that an attempt to select a menuoption by matching a value has failed.
9
- * @event {CustomEvent<{ values: HTMLElement[] }>} auroMenu-deselectPrevented - Notifies that deselection was prevented and includes the affected options in `detail.values`.
10
9
  * @event {CustomEvent<any>} auroMenu-selectValueReset - Notifies that the component value has been reset.
11
10
  * @event {CustomEvent<any>} auroMenu-selectedOption - Notifies that a new menuoption selection has been made.
12
11
  * @slot loadingText - Text to show while loading attribute is set
@@ -15,13 +14,6 @@
15
14
  */
16
15
  export class AuroMenu extends AuroElement {
17
16
  static get properties(): {
18
- /**
19
- * Allows deselecting an already selected option when clicked again in single-select mode.
20
- */
21
- allowDeselect: {
22
- type: BooleanConstructor;
23
- reflect: boolean;
24
- };
25
17
  /**
26
18
  * When true, the entire menu and all options are disabled.
27
19
  */
@@ -29,18 +21,6 @@ export class AuroMenu extends AuroElement {
29
21
  type: BooleanConstructor;
30
22
  reflect: boolean;
31
23
  };
32
- /**
33
- * Indicates whether the menu has a loadingIcon or loadingText to render when in a loading state.
34
- */
35
- hasLoadingPlaceholder: {
36
- type: BooleanConstructor;
37
- };
38
- /**
39
- * @private
40
- */
41
- layout: {
42
- type: StringConstructor;
43
- };
44
24
  /**
45
25
  * Indent level for submenus.
46
26
  * @private
@@ -80,56 +60,33 @@ export class AuroMenu extends AuroElement {
80
60
  reflect: boolean;
81
61
  attribute: string;
82
62
  };
83
- /**
84
- * Specifies the current active menuOption.
85
- */
86
63
  optionActive: {
87
64
  type: ObjectConstructor;
88
- attribute: string;
65
+ attribute: boolean;
89
66
  };
90
- /**
91
- * An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
92
- */
93
67
  optionSelected: {
94
68
  type: ObjectConstructor;
95
- };
96
- options: {
97
- type: ArrayConstructor;
98
- reflect: boolean;
99
69
  attribute: boolean;
100
70
  };
101
- /**
102
- * Sets the size of the menu.
103
- * @type {'sm' | 'md'}
104
- * @default 'sm'
105
- */
106
- size: "sm" | "md";
107
- /**
108
- * When true, selects all options that match the provided value/key when setting value and multiselect is enabled.
109
- */
110
- selectAllMatchingOptions: {
111
- type: BooleanConstructor;
112
- reflect: boolean;
113
- };
114
- /**
115
- * Sets the shape of the menu.
116
- * @type {'box' | 'round'}
117
- * @default 'box'
118
- */
119
- shape: "box" | "round";
120
71
  /**
121
72
  * The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
73
+ * Options marked `disabled` or `static` are not selectable by value; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared (`optionSelected` becomes `undefined`) and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped from the value and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option.
122
74
  */
123
75
  value: {
124
76
  type: StringConstructor;
125
77
  reflect: boolean;
126
78
  attribute: string;
127
79
  };
80
+ layout: {
81
+ type: StringConstructor;
82
+ attribute: string;
83
+ reflect: boolean;
84
+ };
128
85
  };
129
86
  static get styles(): import("lit").CSSResult[];
130
87
  /**
131
88
  * This will register this element with the browser.
132
- * @param {string} [name="auro-menu"] - The name of the element that you want to register.
89
+ * @param {string} [name="auro-menu"] - The name of element that you want to register to.
133
90
  *
134
91
  * @example
135
92
  * AuroMenu.register("custom-menu") // this will register this element to <custom-menu/>
@@ -144,30 +101,41 @@ export class AuroMenu extends AuroElement {
144
101
  * @private
145
102
  */
146
103
  private size;
104
+ value: any;
147
105
  optionSelected: any;
148
106
  matchWord: any;
149
107
  noCheckmark: boolean;
150
- optionActive: any;
108
+ optionActive: Element | undefined;
151
109
  loading: boolean;
152
110
  multiSelect: boolean;
153
- allowDeselect: boolean;
154
- selectAllMatchingOptions: boolean;
155
111
  /**
156
- * Handles slot change events.
112
+ * Handles keyboard navigation and selection.
157
113
  * @private
114
+ * @param {KeyboardEvent} event - The keydown event.
158
115
  */
159
- private handleSlotChange;
116
+ private handleKeyDown;
160
117
  /**
161
- * @readonly
162
- * @returns {string} - Returns the label of the currently selected option(s).
118
+ * Handles option selection via click events from menuoptions.
119
+ * @private
120
+ * @param {CustomEvent} event - The auroMenuOption-click event.
163
121
  */
164
- readonly get currentLabel(): string;
122
+ private handleMouseSelect;
123
+ /**
124
+ * Handles option hover events.
125
+ * @private
126
+ * @param {CustomEvent} event - Event object from the browser.
127
+ */
128
+ private handleOptionHover;
129
+ /**
130
+ * Handles slot change events.
131
+ * @private
132
+ */
133
+ private handleSlotChange;
165
134
  /**
166
135
  * @readonly
167
136
  * @returns {Array<HTMLElement>} - Returns the array of available menu options.
168
- * @deprecated Use `options` property instead.
169
137
  */
170
- readonly get items(): Array<HTMLElement>;
138
+ readonly get options(): Array<HTMLElement>;
171
139
  /**
172
140
  * @param {number} value - Sets the index of the currently active option.
173
141
  */
@@ -177,83 +145,72 @@ export class AuroMenu extends AuroElement {
177
145
  */
178
146
  get index(): number;
179
147
  /**
180
- * Formatted value based on `multiSelect` state.
181
- * Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
182
- * @private
183
- * @returns {String|Array<String>}
184
- */
185
- private get formattedValue();
186
- /**
187
- * Gets the current property values for the menu service.
188
- * @private
189
- * @returns {Object}
190
- */
191
- private get propertyValues();
192
- /**
193
- * Provides the menu context to child components.
194
- * Initializes the MenuService and subscribes to menu changes.
195
- * @protected
196
- */
197
- protected provideContext(): void;
198
- rootMenu: boolean | undefined;
199
- menuService: any;
200
- _contextProvider: any;
201
- /**
202
- * Updates the currently active option in the menu.
203
- * @param {HTMLElement} option - The option to set as active.
148
+ * Gets the currently selected options as an array.
149
+ * @returns {Array<HTMLElement>}
204
150
  */
205
- updateActiveOption(option: HTMLElement): void;
151
+ get selectedOptions(): Array<HTMLElement>;
206
152
  /**
207
- * Sets the internal value and manages update state.
208
- * @param {String|Array<String>} value - The value to set.
209
- * @protected
153
+ * Gets the first selected option, or null if none.
154
+ * @returns {HTMLElement|null}
210
155
  */
211
- protected setInternalValue(value: string | Array<string>): void;
212
- internalUpdateInProgress: boolean | undefined;
213
- value: any;
156
+ get selectedOption(): HTMLElement | null;
214
157
  /**
215
- * Handles changes from the menu service and updates component state.
216
- * @param {Object} event - The event object from the menu service.
217
- * @protected
158
+ * @readonly
159
+ * @returns {string} - Returns the label of the currently selected option(s).
218
160
  */
219
- protected handleMenuChange(event: Object): void;
220
- _index: any;
221
- options: any;
161
+ readonly get currentLabel(): string;
222
162
  /**
223
- * Gets the currently selected options.
224
- * @returns {Array<HTMLElement>}
163
+ * Formatted value based on `multiSelect` state.
164
+ * Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
165
+ * @private
166
+ * @returns {String|Array<String>}
225
167
  */
226
- get selectedOptions(): Array<HTMLElement>;
168
+ private get formattedValue();
227
169
  /**
228
- * Gets the first selected option, or null if none.
229
- * @returns {HTMLElement|null}
170
+ * Selects options by value. Options marked `disabled` or `static` are not selectable; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option. Passing `undefined`, `null`, an empty string, or an empty array clears the selection without dispatching a failure.
171
+ * @param {string|string[]|undefined|null} value - The value(s) to select.
172
+ * @public
230
173
  */
231
- get selectedOption(): HTMLElement | null;
174
+ public selectByValue(value: string | string[] | undefined | null): void;
232
175
  firstUpdated(): void;
233
176
  loadingSlots: NodeListOf<Element> | undefined;
234
- updated(changedProperties: any): void;
235
177
  /**
236
178
  * Sets an attribute that matches the default tag name if the tag name is not the default.
237
179
  * @param {string} tagName - The tag name to set as an attribute.
238
180
  * @private
239
181
  */
240
182
  private setTagAttribute;
183
+ updated(changedProperties: any): void;
184
+ _index: number | undefined;
241
185
  /**
242
- * Sets the loading state and dispatches a loading change event.
243
- * @param {boolean} isLoading - Whether the menu is loading.
244
- * @protected
186
+ * Updates the UI state and appearance of menu items based on changed properties.
187
+ * @private
188
+ * @param {Map<string, boolean>} changedProperties - LitElement's changed properties map.
245
189
  */
246
- protected setLoadingState(isLoading: boolean): void;
190
+ private updateItemsState;
247
191
  /**
248
192
  * Initializes the menu's state and structure.
249
193
  * @private
250
194
  */
251
195
  private initializeMenu;
252
196
  /**
253
- * Selects the currently highlighted option.
254
- * @protected
197
+ * Initializes menu items and their attributes.
198
+ * @private
199
+ */
200
+ private initItems;
201
+ items: Element[] | undefined;
202
+ /**
203
+ * Updates menu state when an option is selected.
204
+ * @private
205
+ * @param {HTMLElement} option - The option element to select.
206
+ */
207
+ private handleSelectState;
208
+ /**
209
+ * Deselects a menu option and updates related state.
210
+ * @private
211
+ * @param {HTMLElement} option - The menuoption to be deselected.
255
212
  */
256
- protected makeSelection(): void;
213
+ private handleDeselectState;
257
214
  /**
258
215
  * Resets all options to their default state.
259
216
  * @private
@@ -272,11 +229,28 @@ export class AuroMenu extends AuroElement {
272
229
  */
273
230
  private handleNestedMenus;
274
231
  /**
275
- * Navigates the menu options in the specified direction.
276
- * @param {'up'|'down'} direction - The direction to navigate.
277
- * @protected
232
+ * Makes a selection based on the current index.
233
+ * @private
234
+ */
235
+ private makeSelection;
236
+ /**
237
+ * Toggle the selection state of the menuoption.
238
+ * @private
239
+ * @param {HTMLElement} option - The menuoption to toggle.
240
+ */
241
+ private toggleOption;
242
+ rootMenu: boolean | undefined;
243
+ /**
244
+ * Navigates through options using keyboard.
245
+ * @param {string} direction - 'up' or 'down'.
246
+ */
247
+ navigateOptions(direction: string): void;
248
+ /**
249
+ * Updates the active option state and dispatches events.
250
+ * Accepts either a numeric index or an HTMLElement option.
251
+ * @param {number|HTMLElement} indexOrOption - Index of the option or the option element to make active.
278
252
  */
279
- protected navigateOptions(direction: "up" | "down"): void;
253
+ updateActiveOption(indexOrOption: number | HTMLElement): void;
280
254
  /**
281
255
  * Handles custom events defined on options.
282
256
  * @private
@@ -289,6 +263,13 @@ export class AuroMenu extends AuroElement {
289
263
  * @private
290
264
  */
291
265
  private notifySelectionChange;
266
+ /**
267
+ * @private
268
+ * @param {any} current - Current selection.
269
+ * @param {any} next - New selection to compare.
270
+ * @returns {boolean} Whether the selections are equal.
271
+ */
272
+ private selectionEquals;
292
273
  /**
293
274
  * Checks if an option is currently selected.
294
275
  * @private