@astryxdesign/core 0.7.1-canary.ff40b78 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/dist/Button/Button.d.ts +1 -1
  3. package/dist/Button/Button.d.ts.map +1 -1
  4. package/dist/Button/Button.js +5 -2
  5. package/dist/Calendar/Calendar.d.ts.map +1 -1
  6. package/dist/Calendar/Calendar.js +191 -32
  7. package/dist/Chat/ChatComposerInput.d.ts +9 -0
  8. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  9. package/dist/Chat/ChatComposerInput.js +5 -0
  10. package/dist/Chat/ChatMessage.d.ts +11 -0
  11. package/dist/Chat/ChatMessage.d.ts.map +1 -1
  12. package/dist/Chat/ChatMessage.js +18 -9
  13. package/dist/Chat/useTriggerMenu.d.ts +9 -2
  14. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  15. package/dist/Chat/useTriggerMenu.js +222 -50
  16. package/dist/CodeBlock/CodeBlock.d.ts +10 -1
  17. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  18. package/dist/CodeBlock/CodeBlock.js +158 -38
  19. package/dist/CodeBlock/tokenizer.d.ts +39 -0
  20. package/dist/CodeBlock/tokenizer.d.ts.map +1 -1
  21. package/dist/CodeBlock/tokenizer.js +108 -0
  22. package/dist/CommandPalette/CommandPalette.d.ts +9 -5
  23. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  24. package/dist/CommandPalette/CommandPalette.js +38 -20
  25. package/dist/CommandPalette/CommandPaletteEmpty.d.ts +4 -3
  26. package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
  27. package/dist/CommandPalette/CommandPaletteEmpty.js +4 -3
  28. package/dist/CommandPalette/CommandPaletteInput.d.ts +5 -4
  29. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  30. package/dist/CommandPalette/CommandPaletteInput.js +35 -18
  31. package/dist/CommandPalette/CommandPaletteItem.d.ts +11 -6
  32. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  33. package/dist/CommandPalette/CommandPaletteItem.js +8 -9
  34. package/dist/CommandPalette/CommandPaletteList.d.ts +4 -2
  35. package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
  36. package/dist/CommandPalette/CommandPaletteList.js +10 -5
  37. package/dist/ComplexSelector/ComplexSelector.d.ts +8 -5
  38. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  39. package/dist/ComplexSelector/ComplexSelector.js +12 -3
  40. package/dist/ContextMenu/ContextMenu.d.ts +3 -3
  41. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  42. package/dist/ContextMenu/ContextMenu.js +62 -48
  43. package/dist/DateInput/DateInput.js +1 -1
  44. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  45. package/dist/DateInput/MonthScroller.js +12 -4
  46. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  47. package/dist/DateRangeInput/DateRangeInput.js +12 -2
  48. package/dist/Dialog/Dialog.d.ts +1 -1
  49. package/dist/Dialog/Dialog.d.ts.map +1 -1
  50. package/dist/Dialog/Dialog.js +16 -5
  51. package/dist/Dialog/DialogHeader.d.ts +1 -1
  52. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  53. package/dist/Dialog/DialogHeader.js +7 -7
  54. package/dist/Divider/Divider.d.ts +1 -0
  55. package/dist/Divider/Divider.d.ts.map +1 -1
  56. package/dist/Divider/Divider.js +5 -4
  57. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  58. package/dist/DropdownMenu/DropdownMenu.js +161 -65
  59. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +7 -5
  60. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  61. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +12 -5
  62. package/dist/Field/InputClearButton.d.ts +8 -4
  63. package/dist/Field/InputClearButton.d.ts.map +1 -1
  64. package/dist/Field/InputClearButton.js +23 -7
  65. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  66. package/dist/FormLayout/FormLayout.js +1 -0
  67. package/dist/Grid/Grid.d.ts +13 -4
  68. package/dist/Grid/Grid.d.ts.map +1 -1
  69. package/dist/Grid/Grid.js +7 -1
  70. package/dist/HoverCard/useHoverCard.d.ts +1 -1
  71. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  72. package/dist/HoverCard/useHoverCard.js +67 -49
  73. package/dist/InputGroup/InputGroup.d.ts +2 -4
  74. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  75. package/dist/InputGroup/InputGroup.js +2 -4
  76. package/dist/InputGroup/groupStyles.d.ts +10 -2
  77. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  78. package/dist/InputGroup/groupStyles.js +19 -2
  79. package/dist/Layer/useLayerDismissal.d.ts +9 -9
  80. package/dist/Layer/useLayerDismissal.js +9 -9
  81. package/dist/Markdown/Markdown.d.ts.map +1 -1
  82. package/dist/Markdown/Markdown.js +25 -4
  83. package/dist/MobileNav/MobileNav.d.ts +7 -0
  84. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  85. package/dist/MobileNav/MobileNav.js +45 -2
  86. package/dist/MultiSelector/MultiSelector.d.ts +7 -4
  87. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  88. package/dist/MultiSelector/MultiSelector.js +24 -3
  89. package/dist/NumberInput/NumberInput.js +1 -1
  90. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  91. package/dist/PowerSearch/PowerSearchEditPopover.js +6 -0
  92. package/dist/Resizable/ResizeHandle.d.ts +1 -1
  93. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  94. package/dist/Resizable/ResizeHandle.js +83 -15
  95. package/dist/Resizable/useResizable.d.ts +23 -0
  96. package/dist/Resizable/useResizable.d.ts.map +1 -1
  97. package/dist/Resizable/useResizable.js +78 -0
  98. package/dist/Selector/Selector.d.ts +6 -3
  99. package/dist/Selector/Selector.d.ts.map +1 -1
  100. package/dist/Selector/Selector.js +28 -6
  101. package/dist/SideNav/SideNav.d.ts.map +1 -1
  102. package/dist/SideNav/SideNav.js +10 -2
  103. package/dist/Slider/Slider.d.ts.map +1 -1
  104. package/dist/Slider/Slider.js +18 -7
  105. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  106. package/dist/Tokenizer/Tokenizer.js +16 -4
  107. package/dist/Toolbar/Toolbar.d.ts +2 -1
  108. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  109. package/dist/Toolbar/Toolbar.js +3 -1
  110. package/dist/TreeList/TreeList.d.ts.map +1 -1
  111. package/dist/TreeList/TreeList.js +6 -3
  112. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  113. package/dist/TreeList/TreeListItem.js +7 -1
  114. package/dist/astryx.css +22 -0
  115. package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
  116. package/dist/hooks/useScrollOverflow.js +55 -12
  117. package/dist/hooks/useTreeFocus.d.ts +21 -0
  118. package/dist/hooks/useTreeFocus.d.ts.map +1 -1
  119. package/dist/hooks/useTreeFocus.js +40 -2
  120. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  121. package/dist/i18n/generated-locales/en.generated.js +3 -0
  122. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  123. package/dist/i18n/generated-locales/pseudo.generated.js +3 -0
  124. package/dist/reset.a11y.chromium.spec.js +6 -1
  125. package/dist/reset.until-found.a11y.browser.spec.d.ts +2 -0
  126. package/dist/reset.until-found.a11y.browser.spec.d.ts.map +1 -0
  127. package/dist/reset.until-found.a11y.browser.spec.js +71 -0
  128. package/dist/theme/syntax/SyntaxTheme.d.ts.map +1 -1
  129. package/dist/theme/syntax/SyntaxTheme.js +43 -2
  130. package/dist/theme/syntax/defineSyntaxTheme.d.ts +18 -5
  131. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  132. package/dist/theme/syntax/defineSyntaxTheme.js +38 -9
  133. package/dist/theme/syntax/index.d.ts +1 -1
  134. package/dist/theme/syntax/index.d.ts.map +1 -1
  135. package/dist/theme/syntax/tokens.d.ts +12 -2
  136. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  137. package/dist/theme/syntax/tokens.js +25 -4
  138. package/dist/utils/plainDate.d.ts +12 -0
  139. package/dist/utils/plainDate.d.ts.map +1 -1
  140. package/dist/utils/plainDate.js +63 -10
  141. package/locales/en.json +13 -1
  142. package/locales/pseudo.json +9 -0
  143. package/package.json +4 -4
  144. package/src/AlertDialog/AlertDialog.doc.mjs +6 -0
  145. package/src/AlertDialog/AlertDialog.spec.md +205 -0
  146. package/src/AlertDialog/AlertDialog.test.tsx +3 -14
  147. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +115 -0
  148. package/src/AlertDialog/__tests__/AlertDialog.a11y.renders.tsx +52 -0
  149. package/src/AlertDialog/__tests__/AlertDialog.a11y.states.ts +68 -0
  150. package/src/AlertDialog/__tests__/AlertDialog.a11y.test.tsx +144 -0
  151. package/src/Button/Button.test.tsx +37 -0
  152. package/src/Button/Button.tsx +5 -1
  153. package/src/Calendar/Calendar.doc.mjs +234 -60
  154. package/src/Calendar/Calendar.spec.md +209 -0
  155. package/src/Calendar/Calendar.test.tsx +559 -20
  156. package/src/Calendar/Calendar.tsx +258 -41
  157. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +126 -0
  158. package/src/Calendar/__tests__/Calendar.a11y.known-failures.ts +12 -0
  159. package/src/Calendar/__tests__/Calendar.a11y.renders.tsx +57 -0
  160. package/src/Calendar/__tests__/Calendar.a11y.states.ts +139 -0
  161. package/src/Calendar/__tests__/Calendar.a11y.test.tsx +137 -0
  162. package/src/Carousel/Carousel.test.tsx +54 -71
  163. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +192 -0
  164. package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +27 -0
  165. package/src/Carousel/__tests__/Carousel.a11y.renders.tsx +39 -0
  166. package/src/Carousel/__tests__/Carousel.a11y.states.ts +139 -0
  167. package/src/Carousel/__tests__/Carousel.a11y.test.tsx +127 -0
  168. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  169. package/src/Chat/ChatComposerInput.spec.md +94 -55
  170. package/src/Chat/ChatComposerInput.test.tsx +202 -1
  171. package/src/Chat/ChatComposerInput.tsx +13 -0
  172. package/src/Chat/ChatMessage.doc.mjs +31 -16
  173. package/src/Chat/ChatMessage.spec.md +265 -0
  174. package/src/Chat/ChatMessage.test.tsx +246 -0
  175. package/src/Chat/ChatMessage.tsx +30 -7
  176. package/src/Chat/ChatSystemMessage.spec.md +36 -37
  177. package/src/Chat/ChatSystemMessage.test.tsx +4 -4
  178. package/src/Chat/useTriggerMenu.test.tsx +994 -0
  179. package/src/Chat/useTriggerMenu.tsx +278 -46
  180. package/src/CodeBlock/CodeBlock.doc.mjs +7 -0
  181. package/src/CodeBlock/CodeBlock.spec.md +40 -41
  182. package/src/CodeBlock/CodeBlock.test.tsx +89 -9
  183. package/src/CodeBlock/CodeBlock.tsx +205 -25
  184. package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +125 -0
  185. package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +93 -0
  186. package/src/CodeBlock/tokenizer.test.ts +112 -0
  187. package/src/CodeBlock/tokenizer.ts +106 -0
  188. package/src/Collapsible/CollapsibleGroup.spec.md +17 -8
  189. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.renders.tsx +45 -0
  190. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.states.ts +139 -0
  191. package/src/Collapsible/__tests__/CollapsibleGroup.a11y.test.tsx +135 -0
  192. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +128 -0
  193. package/src/CommandPalette/CommandPalette.doc.mjs +126 -23
  194. package/src/CommandPalette/CommandPalette.spec.md +100 -49
  195. package/src/CommandPalette/CommandPalette.test.tsx +241 -2
  196. package/src/CommandPalette/CommandPalette.tsx +47 -21
  197. package/src/CommandPalette/CommandPaletteEmpty.tsx +4 -3
  198. package/src/CommandPalette/CommandPaletteInput.doc.mjs +61 -4
  199. package/src/CommandPalette/CommandPaletteInput.spec.md +215 -0
  200. package/src/CommandPalette/CommandPaletteInput.test.tsx +375 -51
  201. package/src/CommandPalette/CommandPaletteInput.tsx +74 -21
  202. package/src/CommandPalette/CommandPaletteItem.doc.mjs +73 -22
  203. package/src/CommandPalette/CommandPaletteItem.spec.md +223 -0
  204. package/src/CommandPalette/CommandPaletteItem.test.tsx +200 -5
  205. package/src/CommandPalette/CommandPaletteItem.tsx +16 -11
  206. package/src/CommandPalette/CommandPaletteList.doc.mjs +3 -3
  207. package/src/CommandPalette/CommandPaletteList.spec.md +41 -36
  208. package/src/CommandPalette/CommandPaletteList.test.tsx +80 -0
  209. package/src/CommandPalette/CommandPaletteList.tsx +10 -5
  210. package/src/CommandPalette/__tests__/CommandPalette.a11y.chromium.spec.ts +599 -0
  211. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -8
  212. package/src/ComplexSelector/ComplexSelector.spec.md +14 -9
  213. package/src/ComplexSelector/ComplexSelector.test.tsx +64 -16
  214. package/src/ComplexSelector/ComplexSelector.tsx +37 -8
  215. package/src/ContextMenu/ContextMenu.doc.mjs +6 -0
  216. package/src/ContextMenu/ContextMenu.spec.md +51 -53
  217. package/src/ContextMenu/ContextMenu.test.tsx +132 -1
  218. package/src/ContextMenu/ContextMenu.tsx +78 -48
  219. package/src/DateInput/DateInput.doc.mjs +52 -0
  220. package/src/DateInput/DateInput.spec.md +27 -15
  221. package/src/DateInput/DateInput.test.tsx +38 -0
  222. package/src/DateInput/DateInput.tsx +1 -1
  223. package/src/DateInput/DateInputTouch.test.tsx +22 -0
  224. package/src/DateInput/MonthScroller.tsx +12 -4
  225. package/src/DateRangeInput/DateRangeInput.test.tsx +49 -0
  226. package/src/DateRangeInput/DateRangeInput.tsx +20 -2
  227. package/src/Dialog/Dialog.test.tsx +27 -1
  228. package/src/Dialog/Dialog.tsx +16 -5
  229. package/src/Dialog/DialogHeader.test.tsx +27 -2
  230. package/src/Dialog/DialogHeader.tsx +7 -8
  231. package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +21 -14
  232. package/src/Divider/Divider.doc.mjs +5 -3
  233. package/src/Divider/Divider.spec.md +140 -54
  234. package/src/Divider/Divider.test.tsx +15 -0
  235. package/src/Divider/Divider.tsx +6 -4
  236. package/src/DropdownMenu/DropdownMenu.doc.mjs +2 -2
  237. package/src/DropdownMenu/DropdownMenu.spec.md +121 -45
  238. package/src/DropdownMenu/DropdownMenu.test.tsx +288 -23
  239. package/src/DropdownMenu/DropdownMenu.tsx +212 -81
  240. package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +38 -2
  241. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +32 -18
  242. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +146 -1
  243. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +136 -0
  244. package/src/DropdownMenu/__tests__/MenuButton.a11y.known-failures.ts +12 -0
  245. package/src/DropdownMenu/__tests__/MenuButton.a11y.renders.tsx +67 -0
  246. package/src/DropdownMenu/__tests__/MenuButton.a11y.states.ts +141 -0
  247. package/src/DropdownMenu/__tests__/MenuButton.a11y.test.tsx +138 -0
  248. package/src/DropdownMenu/__tests__/MenuHeaderFooter.a11y.chromium.spec.ts +40 -5
  249. package/src/Field/InputClearButton.test.tsx +29 -4
  250. package/src/Field/InputClearButton.tsx +26 -8
  251. package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +21 -14
  252. package/src/FormLayout/FormLayout.tsx +1 -0
  253. package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +1 -1
  254. package/src/Grid/Grid.doc.mjs +14 -11
  255. package/src/Grid/Grid.spec.md +50 -32
  256. package/src/Grid/Grid.tsx +13 -4
  257. package/src/HoverCard/HoverCard.test.tsx +46 -1
  258. package/src/HoverCard/useHoverCard.tsx +68 -48
  259. package/src/InputGroup/InputGroup.doc.mjs +11 -1
  260. package/src/InputGroup/InputGroup.tsx +2 -4
  261. package/src/InputGroup/groupStyles.ts +40 -2
  262. package/src/Layer/useLayerDismissal.ts +9 -9
  263. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +142 -0
  264. package/src/Link/__tests__/Link.a11y.renders.tsx +97 -0
  265. package/src/Link/__tests__/Link.a11y.states.ts +104 -0
  266. package/src/Link/__tests__/Link.a11y.test.tsx +127 -0
  267. package/src/Markdown/Markdown.doc.mjs +1 -1
  268. package/src/Markdown/Markdown.fr23.perf.test.ts +161 -40
  269. package/src/Markdown/Markdown.spec.md +45 -23
  270. package/src/Markdown/Markdown.test.tsx +38 -0
  271. package/src/Markdown/Markdown.tsx +24 -2
  272. package/src/Markdown/plugins/semanticFence.test.tsx +3 -2
  273. package/src/MobileNav/MobileNav.tsx +50 -2
  274. package/src/MobileNav/MobileNavFocus.test.tsx +553 -0
  275. package/src/MoreMenu/MoreMenu.spec.md +18 -7
  276. package/src/MoreMenu/MoreMenu.test.tsx +38 -0
  277. package/src/MultiSelector/MultiSelector.doc.mjs +8 -8
  278. package/src/MultiSelector/MultiSelector.spec.md +1 -1
  279. package/src/MultiSelector/MultiSelector.test.tsx +188 -21
  280. package/src/MultiSelector/MultiSelector.tsx +50 -11
  281. package/src/NumberInput/NumberInput.test.tsx +24 -0
  282. package/src/NumberInput/NumberInput.tsx +1 -1
  283. package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +22 -15
  284. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +78 -0
  285. package/src/PowerSearch/PowerSearchEditPopover.tsx +6 -0
  286. package/src/Resizable/Resizable.spec.md +41 -9
  287. package/src/Resizable/ResizeHandle.test.tsx +565 -2
  288. package/src/Resizable/ResizeHandle.tsx +126 -21
  289. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +119 -0
  290. package/src/Resizable/__tests__/ResizeHandle.a11y.known-failures.ts +39 -0
  291. package/src/Resizable/__tests__/ResizeHandle.a11y.renders.tsx +80 -0
  292. package/src/Resizable/__tests__/ResizeHandle.a11y.states.ts +197 -0
  293. package/src/Resizable/__tests__/ResizeHandle.a11y.test.tsx +123 -0
  294. package/src/Resizable/useResizable.ts +95 -0
  295. package/src/Selector/Selector.doc.mjs +7 -6
  296. package/src/Selector/Selector.spec.md +37 -24
  297. package/src/Selector/Selector.test.tsx +176 -10
  298. package/src/Selector/Selector.tsx +59 -14
  299. package/src/Selector/__tests__/Combobox.a11y.known-failures.ts +27 -0
  300. package/src/Selector/__tests__/Combobox.a11y.states.ts +145 -0
  301. package/src/Selector/__tests__/Selector.combobox.a11y.chromium.spec.ts +108 -0
  302. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +126 -0
  303. package/src/SideNav/SideNav.test.tsx +35 -0
  304. package/src/SideNav/SideNav.tsx +16 -2
  305. package/src/Slider/Slider.spec.md +43 -17
  306. package/src/Slider/Slider.test.tsx +134 -0
  307. package/src/Slider/Slider.tsx +29 -6
  308. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +112 -0
  309. package/src/Slider/__tests__/Slider.a11y.known-failures.ts +12 -0
  310. package/src/Slider/__tests__/Slider.a11y.renders.tsx +42 -0
  311. package/src/Slider/__tests__/Slider.a11y.states.ts +106 -0
  312. package/src/Slider/__tests__/Slider.a11y.test.tsx +105 -0
  313. package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +25 -18
  314. package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +19 -12
  315. package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +21 -14
  316. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +18 -11
  317. package/src/Tokenizer/Tokenizer.test.tsx +87 -0
  318. package/src/Tokenizer/Tokenizer.tsx +31 -3
  319. package/src/Toolbar/Toolbar.test.tsx +131 -4
  320. package/src/Toolbar/Toolbar.tsx +3 -1
  321. package/src/TreeList/TreeList.spec.md +33 -8
  322. package/src/TreeList/TreeList.test.tsx +72 -0
  323. package/src/TreeList/TreeList.tsx +10 -6
  324. package/src/TreeList/TreeListItem.tsx +5 -0
  325. package/src/TreeList/__tests__/TreeList.a11y.chromium.spec.ts +125 -0
  326. package/src/TreeList/__tests__/TreeList.a11y.renders.tsx +44 -0
  327. package/src/TreeList/__tests__/TreeList.a11y.states.ts +164 -0
  328. package/src/TreeList/__tests__/TreeList.a11y.test.tsx +138 -0
  329. package/src/TreeList/__tests__/TreeListRowNames.a11y.chromium.spec.ts +82 -0
  330. package/src/hooks/useScrollOverflow.test.tsx +222 -0
  331. package/src/hooks/useScrollOverflow.ts +55 -13
  332. package/src/hooks/useTreeFocus.test.tsx +37 -0
  333. package/src/hooks/useTreeFocus.ts +55 -2
  334. package/src/i18n/generated-locales/en.generated.ts +3 -0
  335. package/src/i18n/generated-locales/pseudo.generated.ts +3 -0
  336. package/src/reset.a11y.chromium.spec.ts +9 -1
  337. package/src/reset.css +8 -3
  338. package/src/reset.until-found.a11y.browser.spec.ts +75 -0
  339. package/src/reset.until-found.test.ts +32 -0
  340. package/src/stylexValidation.source-build.test.mjs +42 -0
  341. package/src/theme/syntax/SyntaxTheme.tsx +46 -5
  342. package/src/theme/syntax/defineSyntaxTheme.diff.test.ts +91 -0
  343. package/src/theme/syntax/defineSyntaxTheme.ts +75 -15
  344. package/src/theme/syntax/index.ts +5 -1
  345. package/src/theme/syntax/tokens.ts +32 -2
  346. package/src/theme/syntax/useSyntaxTheme.diff.test.tsx +40 -0
  347. package/src/utils/plainDate.test.ts +147 -0
  348. package/src/utils/plainDate.ts +75 -10
@@ -74,7 +74,11 @@ export interface CommandPaletteItemProps extends Omit<
74
74
  ref?: React.Ref<HTMLDivElement>;
75
75
  /** Unique value for identification and selection. */
76
76
  value: string;
77
- /** Called when this item is selected (via click or Enter). */
77
+ /**
78
+ * Called after this item is activated by pointer.
79
+ * Keyboard selection inside CommandPalette reports through the root
80
+ * `onValueChange` callback.
81
+ */
78
82
  onSelect?: (value: string) => void;
79
83
  /**
80
84
  * Whether this item is visually highlighted (keyboard focus).
@@ -92,7 +96,7 @@ export interface CommandPaletteItemProps extends Omit<
92
96
  * @default false
93
97
  */
94
98
  isDisabled?: boolean;
95
- /** Item content. Fully custom — render icons, descriptions, shortcuts, etc. */
99
+ /** Non-interactive item content: labels, icons, descriptions, shortcuts, etc. */
96
100
  children: ReactNode;
97
101
  }
98
102
 
@@ -100,9 +104,10 @@ export interface CommandPaletteItemProps extends Omit<
100
104
  * A selectable item in the command palette.
101
105
  * Accepts arbitrary children for full rendering control.
102
106
  *
103
- * When used inside CommandPalette, registers with context for
104
- * keyboard navigation and selection. Can also be used
105
- * standalone with explicit isHighlighted/isSelected props.
107
+ * When used inside CommandPalette, context supplies identity, highlight,
108
+ * selection, and close behavior. Standalone use supports explicit visual
109
+ * state and pointer activation but does not provide a composite listbox
110
+ * keyboard model.
106
111
  *
107
112
  * @compositionHint Place inside CommandPaletteList or CommandPaletteGroup.
108
113
  *
@@ -124,6 +129,7 @@ export function CommandPaletteItem({
124
129
  xstyle,
125
130
  className,
126
131
  style,
132
+ id: idProp,
127
133
  onClick: onClickProp,
128
134
  onMouseEnter: onMouseEnterProp,
129
135
  ...props
@@ -174,27 +180,26 @@ export function CommandPaletteItem({
174
180
  }, [ctx, isHighlighted, isInlineDialog]);
175
181
 
176
182
  const handleClick = useCallback(() => {
177
- if (isDisabled) {
178
- return;
179
- }
180
183
  onSelect?.(value);
181
184
  if (ctx) {
182
185
  ctx.selectItem(value);
183
186
  ctx.onClose();
184
187
  }
185
- }, [isDisabled, value, onSelect, ctx]);
188
+ }, [value, onSelect, ctx]);
186
189
 
187
190
  return (
188
191
  <div
189
192
  ref={useMergedRefs(ref, itemRef)}
190
193
  {...props}
191
- id={ctx && itemIndex >= 0 ? ctx.getItemId(itemIndex) : undefined}
194
+ id={ctx && itemIndex >= 0 ? ctx.getItemId(itemIndex) : idProp}
192
195
  role="option"
193
196
  aria-selected={isSelected}
194
197
  aria-disabled={isDisabled || undefined}
195
198
  data-value={value}
196
199
  {...pressable}
197
- onClick={composeEventHandlers(onClickProp, handleClick)}
200
+ onClick={
201
+ isDisabled ? undefined : composeEventHandlers(onClickProp, handleClick)
202
+ }
198
203
  onMouseEnter={onMouseEnterProp}
199
204
  {...mergeProps(
200
205
  themeProps('command-palette-item'),
@@ -7,7 +7,7 @@ export const docs = {
7
7
  subComponentOf: 'CommandPalette',
8
8
  displayName: 'Command Palette List',
9
9
  isHiddenFromOverview: true,
10
- description: 'Scrollable results container. Renders as a listbox for ARIA. Contains CommandPaletteItem and CommandPaletteGroup children.',
10
+ description: 'Scrollable results container. Renders as a listbox standalone, and inside CommandPalette while selectable results exist. Contains CommandPaletteItem and CommandPaletteGroup children.',
11
11
  props: [
12
12
  {
13
13
  name: 'children',
@@ -42,7 +42,7 @@ export const docsZh = {
42
42
  name: 'CommandPaletteList',
43
43
  isHiddenFromOverview: true,
44
44
  displayName: 'Command Palette List',
45
- description: '可滚动的结果容器。作为 listbox 渲染以符合 ARIA 规范。',
45
+ description: '可滚动的结果容器。独立使用时,以及在 CommandPalette 中存在可选结果时,作为 listbox 渲染。',
46
46
  propDescriptions: {
47
47
  children: '条目、分组和空状态。',
48
48
  label: 'listbox 的无障碍标签。',
@@ -54,7 +54,7 @@ export const docsDense = {
54
54
  name: 'CommandPaletteList',
55
55
  isHiddenFromOverview: true,
56
56
  displayName: 'Command Palette List',
57
- description: 'scrollable results container; role=listbox',
57
+ description: 'scrollable results container; role=listbox standalone, and in CommandPalette only while results exist',
58
58
  propDescriptions: {
59
59
  children: 'items, groups, empty states',
60
60
  label: 'a11y label for listbox',
@@ -36,15 +36,15 @@ system_specs: []
36
36
 
37
37
  ## Contract at a glance
38
38
 
39
- | Area | Contract |
40
- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
- | Public contract | None changes. One named listbox container for result options, rendered by CommandPalette or directly for a standalone results list. |
42
- | Behavior | The root is a `listbox` named by `label` or the translated default; inside CommandPalette it carries the context list id that the query field controls. |
43
- | End-user impact | Screen-reader users reach a named results list from the query field; overflowing results scroll inside the list instead of growing the palette. |
44
- | Builder impact | None. CommandPalette renders its own list; standalone compositions render items and groups directly inside this one. |
45
- | Compatibility/readiness | Observational draft with no runtime change. A standalone caller `id` is overwritten (FR1), an empty list keeps the listbox role (AR4), and the standalone keyboard model remains OQ1. |
46
- | Review checks | Reject a second list-id owner, a role or name that consumer props can replace, dropped native or styling inputs, or a list target moved off the scrolling root. |
47
- | Governing rules | `architecture:public-component-api/INV5,INV6,INV8`; `architecture:component-theming-surface`; WAI-ARIA 1.2 `listbox`. |
39
+ | Area | Contract |
40
+ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
+ | Public contract | None changes. One named listbox container for result options, rendered by CommandPalette or directly for a standalone results list. |
42
+ | Behavior | The root is a `listbox` named by `label` or the translated default; inside CommandPalette it is one only while selectable results exist, and carries the context list id the query field controls. |
43
+ | End-user impact | Screen-reader users reach a named results list from the query field; overflowing results scroll inside the list instead of growing the palette. |
44
+ | Builder impact | None. CommandPalette renders its own list; standalone compositions render items and groups directly inside this one. |
45
+ | Compatibility/readiness | Draft. Inside CommandPalette an empty or pending result surface drops the listbox role and name (AR4, an accessibility fix); a standalone caller `id` is kept (FR1); the standalone keyboard model remains OQ1. |
46
+ | Review checks | Reject a second list-id owner, a role or name that consumer props can replace, dropped native or styling inputs, or a list target moved off the scrolling root. |
47
+ | Governing rules | `architecture:public-component-api/INV5,INV6,INV8`; `architecture:component-theming-surface`; WAI-ARIA 1.2 `listbox`. |
48
48
 
49
49
  This table is a review projection; the body below is authoritative.
50
50
 
@@ -56,9 +56,10 @@ presents a named results listbox around caller-provided option content.
56
56
 
57
57
  ## Compatibility and migration
58
58
 
59
- - Released default preserved: `yes`
60
- - Compatibility class: observational record only; runtime, DOM, styling, target,
61
- and public API are unchanged
59
+ - Released default preserved: `yes`, except inside CommandPalette while no
60
+ selectable result exists, where the root no longer exposes an empty listbox
61
+ - Compatibility class: accessibility behavior fix (`spec:AST-017/FR53`); styling,
62
+ target, and public API are unchanged
62
63
  - Controlled/uncontrolled behavior: not applicable; the list holds no state
63
64
  - Migration decision: none
64
65
 
@@ -69,7 +70,8 @@ Consumer migration instructions belong in consumer docs and release notes.
69
70
  **Owns**
70
71
 
71
72
  - The listbox root and its accessible name from `label`, falling back to the
72
- translated default.
73
+ translated default, and dropping both inside CommandPalette while no selectable
74
+ result exists.
73
75
  - Applying the CommandPalette context list id to the root.
74
76
  - Native passthrough, `ref`, and styling-input composition on the root.
75
77
  - Block-axis scrolling of overflowing children, with spacing-scale padding and
@@ -91,31 +93,32 @@ Consumer migration instructions belong in consumer docs and release notes.
91
93
  | Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
92
94
  | --------------- | ---------------------------------- | ------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------- | ------------------------------ | --------- | ------------------------------------------------------------------------ |
93
95
  | Accessible name | caller `label`; translated default | Name announced for the results listbox. | All uses | `@astryx.commandPalette.list.label` ("Commands" in English) | `component:CommandPaletteList` | Stable | An empty `label` leaves the listbox unnamed; callers supply a real name. |
94
- | List identity | context list id; absent | DOM id the CommandPalette query field references. | Inside CommandPalette; standalone | Context id inside CommandPalette; absent standalone | `component:CommandPalette` | Stable | A standalone caller `id` is overwritten (FR1 gap). |
96
+ | List identity | context list id; caller `id` | DOM id the CommandPalette query field references. | Inside CommandPalette; standalone | Context id inside CommandPalette; caller `id` standalone | `component:CommandPalette` | Stable | Inside CommandPalette a caller `id` is replaced by the context id. |
95
97
 
96
98
  ## Behavioral and layout contract
97
99
 
98
- | ID | Candidate invariant | Basis | Draft review state |
99
- | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
100
- | FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, an absent id replaces a caller `id`. | Released source; `architecture:public-component-api/INV5,INV6,INV8` | Ref and styling verified by focused tests; the standalone `id` conflicts with INV5 |
101
- | FR2 | The root exposes `role=listbox` with an accessible name from `label`, falling back to the translated default; consumer `role` and `aria-label` props do not replace them. | Released source and docs; WAI-ARIA 1.2 `listbox` | Role and name verified by focused tests; consumer-prop precedence is source-verified; the role also applies with no option (AR4) |
102
- | FR3 | Inside CommandPalette, the query field's `aria-controls` names the listbox id. | Released source and component docs | Verified by a focused composition test |
103
- | FR4 | The root lays out children in one column with spacing-scale padding and gaps, grows within a flex parent, caps its height at the parent's height, and scrolls overflowing children inside itself. | Released source and component docs | Source-verified; the scrolling fixture renders it in a browser, but scroll geometry is not yet measured |
100
+ | ID | Candidate invariant | Basis | Draft review state |
101
+ | --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
102
+ | FR1 | Native props and `ref` reach the listbox root, and consumer `className` and `style` combine with the list target and base styles. Inside CommandPalette the root id is the context list id; standalone, a caller `id` is kept. | Released source; `architecture:public-component-api/INV5,INV6,INV8` | Ref, styling, and the standalone `id` verified by focused tests |
103
+ | FR2 | Standalone, and inside CommandPalette while at least one selectable result exists, the root exposes `role=listbox` with an accessible name from `label`, falling back to the translated default; consumer `role` and `aria-label` props do not replace them. Otherwise AR4 applies. | Released source and docs; WAI-ARIA 1.2 `listbox` | Role and name verified by focused tests, with and without palette results; consumer-prop precedence is source-verified |
104
+ | FR3 | Inside CommandPalette, the query field's `aria-controls` names the listbox id. | Released source and component docs | Verified by a focused composition test |
105
+ | FR4 | The root lays out children in one column with spacing-scale padding and gaps, grows within a flex parent, caps its height at the parent's height, and scrolls overflowing children inside itself. | Released source and component docs | Source-verified; the scrolling fixture renders it in a browser, but scroll geometry is not yet measured |
104
106
 
105
107
  ### Allowed variation
106
108
 
107
109
  - **AV1 — Children.** Items, groups, and empty states may vary in count, order,
108
- and content without changing the listbox root.
110
+ and content without changing the root, except as AR4 states.
109
111
  - **AV2 — Layout.** Consumer `xstyle`, class, and style may adjust the root
110
112
  without replacing its role, name, id, or target.
111
113
 
112
114
  ### Representative states
113
115
 
114
- | State | Required invariant | Allowed variation |
115
- | --------------------- | --------------------------------------------------------------------- | -------------------------- |
116
- | Standalone results | The listbox is named by `label` or the translated default. | Item count and grouping. |
117
- | Inside CommandPalette | The root id equals the query field's `aria-controls` value. | Results count and groups. |
118
- | Overflowing results | Results scroll inside the list instead of growing past the container. | Container and item height. |
116
+ | State | Required invariant | Allowed variation |
117
+ | --------------------- | ------------------------------------------------------------------------------ | -------------------------- |
118
+ | Standalone results | The listbox is named by `label` or the translated default. | Item count and grouping. |
119
+ | Inside CommandPalette | The root id equals the query field's `aria-controls` value. | Results count and groups. |
120
+ | Overflowing results | Results scroll inside the list instead of growing past the container. | Container and item height. |
121
+ | Empty palette results | Inside CommandPalette with no selectable result, the root has no role or name. | Empty or pending message. |
119
122
 
120
123
  ### Transformation and precedence order
121
124
 
@@ -139,9 +142,11 @@ Consumer migration instructions belong in consumer docs and release notes.
139
142
  - **AR3 — Standalone gap.** A standalone list exposes a listbox of options with
140
143
  no owning keyboard model. OQ1 must settle that contract before runtime
141
144
  semantics change.
142
- - **AR4 — Empty content.** The root keeps `role=listbox` when its children contain
143
- no option, as in CommandPalette's empty states. WAI-ARIA 1.2 requires a listbox
144
- to own options, so this is an open conflict, not a contract.
145
+ - **AR4 — Empty content.** Inside CommandPalette, while no selectable result
146
+ exists, the root has no role and no accessible name, so screen readers meet the
147
+ empty or pending message as plain content and no empty popup; WAI-ARIA 1.2
148
+ requires a listbox to own options. A standalone list stays a listbox, and its
149
+ caller supplies the options.
145
150
 
146
151
  ## Design relationships
147
152
 
@@ -163,17 +168,17 @@ Consumer migration instructions belong in consumer docs and release notes.
163
168
 
164
169
  ## Verification map
165
170
 
166
- | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
167
- | -------- | --------------------------------------------------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
168
- | FR1 | `CommandPaletteList.test.tsx` | standalone root with ref, class, and style | Disconnecting `ref`, or dropping the consumer class or the list target, fails focused DOM assertions. | `audit:CommandPaletteList/api` |
169
- | FR2, AR1 | `CommandPaletteList.test.tsx` | default and caller label | Removing the role or name fails the role and name assertions. | `audit:CommandPaletteList/a11y` |
170
- | FR3, AR2 | `CommandPaletteList.test.tsx`, `CommandPalette.test.tsx` | inline CommandPalette | Dropping the context id breaks the query-field relationship assertion. | `audit:CommandPaletteList/a11y` |
171
- | FR4 | Storybook fixtures, `themingTargets.test.ts`, exact-head accessibility and RTL evidence | standalone list; scrolling palette | Losing the target fails the target inventory; any new directional behavior requires a non-empty RTL dimension. | `audit:CommandPaletteList/theming` |
171
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
172
+ | ------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
173
+ | FR1 | `CommandPaletteList.test.tsx` | standalone root with ref, class, and style | Disconnecting `ref`, or dropping the consumer class or the list target, fails focused DOM assertions. | `audit:CommandPaletteList/api` |
174
+ | FR2, AR1, AR4 | `CommandPaletteList.test.tsx` | default and caller label; palette with and without results | Removing the role or name, or keeping them on an empty palette surface, fails the role and name assertions. | `audit:CommandPaletteList/a11y` |
175
+ | FR3, AR2 | `CommandPaletteList.test.tsx`, `CommandPalette.test.tsx` | inline CommandPalette | Dropping the context id breaks the query-field relationship assertion. | `audit:CommandPaletteList/a11y` |
176
+ | FR4 | Storybook fixtures, `themingTargets.test.ts`, exact-head accessibility and RTL evidence | standalone list; scrolling palette | Losing the target fails the target inventory; any new directional behavior requires a non-empty RTL dimension. | `audit:CommandPaletteList/theming` |
172
177
 
173
178
  ## Decision log
174
179
 
175
180
  None. This draft records current facts and settles no component-local API,
176
- keyboard, or visual decision.
181
+ keyboard, or visual decision; AR4 applies the WAI-ARIA 1.2 listbox rule.
177
182
 
178
183
  ## Open questions
179
184
 
@@ -11,8 +11,35 @@ import {createRef} from 'react';
11
11
  import {render, screen} from '@testing-library/react';
12
12
  import {createStaticSource} from '@astryxdesign/core/Typeahead';
13
13
  import {CommandPalette} from './CommandPalette';
14
+ import {
15
+ CommandPaletteContext,
16
+ type CommandPaletteContextValue,
17
+ } from './CommandPaletteContext';
14
18
  import {CommandPaletteList} from './CommandPaletteList';
15
19
 
20
+ function makeContext(
21
+ overrides: Partial<CommandPaletteContextValue> = {},
22
+ ): CommandPaletteContextValue {
23
+ return {
24
+ search: '',
25
+ setSearch: () => {},
26
+ value: '',
27
+ setValue: () => {},
28
+ listId: 'command-list',
29
+ highlightedIndex: -1,
30
+ setHighlightedIndex: () => {},
31
+ getItemId: index => `command-item-${index}`,
32
+ selectableItems: [],
33
+ searchResults: [],
34
+ selectItem: () => {},
35
+ onKeyDown: () => {},
36
+ onClose: () => {},
37
+ isOpen: true,
38
+ isBusy: false,
39
+ ...overrides,
40
+ };
41
+ }
42
+
16
43
  describe('CommandPaletteList', () => {
17
44
  it('renders children', () => {
18
45
  render(
@@ -34,6 +61,59 @@ describe('CommandPaletteList', () => {
34
61
  expect(screen.getByRole('listbox')).toBeInTheDocument();
35
62
  });
36
63
 
64
+ it('carries the stable list theme target', () => {
65
+ render(
66
+ <CommandPaletteList>
67
+ <div>Item</div>
68
+ </CommandPaletteList>,
69
+ );
70
+ expect(screen.getByRole('listbox')).toHaveClass(
71
+ 'astryx-command-palette-list',
72
+ );
73
+ });
74
+
75
+ it('preserves the consumer id when used standalone', () => {
76
+ render(
77
+ <CommandPaletteList id="custom-commands">
78
+ <div>Item</div>
79
+ </CommandPaletteList>,
80
+ );
81
+
82
+ expect(screen.getByRole('listbox')).toHaveAttribute(
83
+ 'id',
84
+ 'custom-commands',
85
+ );
86
+ });
87
+
88
+ it('inside a palette, is a listbox only while it holds selectable results', () => {
89
+ const {rerender} = render(
90
+ <CommandPaletteContext value={makeContext()}>
91
+ <CommandPaletteList>
92
+ <div>No results</div>
93
+ </CommandPaletteList>
94
+ </CommandPaletteContext>,
95
+ );
96
+ expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
97
+ expect(screen.getByText('No results').parentElement).not.toHaveAttribute(
98
+ 'aria-label',
99
+ );
100
+
101
+ rerender(
102
+ <CommandPaletteContext
103
+ value={makeContext({
104
+ selectableItems: [{value: 'open', label: 'Open'}],
105
+ })}>
106
+ <CommandPaletteList>
107
+ <div>Open</div>
108
+ </CommandPaletteList>
109
+ </CommandPaletteContext>,
110
+ );
111
+ expect(screen.getByRole('listbox', {name: 'Commands'})).toHaveAttribute(
112
+ 'id',
113
+ 'command-list',
114
+ );
115
+ });
116
+
37
117
  it('has default aria-label', () => {
38
118
  render(
39
119
  <CommandPaletteList>
@@ -53,8 +53,10 @@ export interface CommandPaletteListProps extends BaseProps<HTMLDivElement> {
53
53
  }
54
54
 
55
55
  /**
56
- * Scrollable results container for the command palette.
57
- * Renders as a listbox for ARIA compliance.
56
+ * Scrollable results container for the command palette. Standalone composition
57
+ * renders as a listbox. Inside CommandPalette, listbox semantics are present
58
+ * only while selectable results exist; empty and pending states retain the same
59
+ * styled container without exposing an empty interactive popup.
58
60
  *
59
61
  * When used inside CommandPalette, automatically gets the correct
60
62
  * ID for aria-controls linking with the input.
@@ -84,14 +86,17 @@ export function CommandPaletteList({
84
86
  const t = useTranslator();
85
87
  const label = labelFromProps ?? t('@astryx.commandPalette.list.label');
86
88
  const ctx = useCommandPaletteContext();
89
+ // Inside CommandPalette the list is a listbox only while it holds selectable
90
+ // results; standalone composition is always a listbox.
91
+ const hasListbox = ctx ? ctx.selectableItems.length > 0 : true;
87
92
 
88
93
  return (
89
94
  <div
90
95
  ref={ref}
91
96
  {...props}
92
- id={ctx?.listId}
93
- role="listbox"
94
- aria-label={label}
97
+ id={ctx?.listId ?? props.id}
98
+ role={hasListbox ? 'listbox' : undefined}
99
+ aria-label={hasListbox ? label : undefined}
95
100
  {...mergeProps(
96
101
  themeProps('command-palette-list'),
97
102
  stylex.props(styles.list, xstyle),