@astryxdesign/core 0.1.8 → 0.1.9

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 (487) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +6 -2
  4. package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
  5. package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
  6. package/dist/Avatar/Avatar.d.ts +18 -2
  7. package/dist/Avatar/Avatar.d.ts.map +1 -1
  8. package/dist/Avatar/Avatar.js +63 -7
  9. package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
  10. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  11. package/dist/Avatar/AvatarStatusDot.js +144 -19
  12. package/dist/Banner/Banner.d.ts +9 -1
  13. package/dist/Banner/Banner.d.ts.map +1 -1
  14. package/dist/Banner/Banner.js +31 -2
  15. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
  16. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  17. package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
  18. package/dist/Breadcrumbs/index.d.ts +5 -0
  19. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  20. package/dist/Breadcrumbs/index.js +9 -1
  21. package/dist/Button/Button.d.ts +8 -2
  22. package/dist/Button/Button.d.ts.map +1 -1
  23. package/dist/Button/Button.js +31 -2
  24. package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
  25. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  26. package/dist/ButtonGroup/ButtonGroup.js +30 -1
  27. package/dist/Calendar/Calendar.d.ts.map +1 -1
  28. package/dist/Calendar/Calendar.js +30 -2
  29. package/dist/Calendar/dayCellUtils.js +1 -1
  30. package/dist/Card/Card.d.ts +8 -2
  31. package/dist/Card/Card.d.ts.map +1 -1
  32. package/dist/Card/Card.js +28 -2
  33. package/dist/Carousel/Carousel.d.ts +4 -1
  34. package/dist/Carousel/Carousel.d.ts.map +1 -1
  35. package/dist/Carousel/Carousel.js +24 -4
  36. package/dist/Chat/ChatComposer.d.ts +8 -0
  37. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  38. package/dist/Chat/ChatComposer.js +46 -7
  39. package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
  40. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  41. package/dist/Chat/ChatComposerDrawer.js +11 -1
  42. package/dist/Chat/ChatComposerInput.d.ts +20 -3
  43. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  44. package/dist/Chat/ChatComposerInput.js +35 -3
  45. package/dist/Chat/ChatContext.d.ts +33 -0
  46. package/dist/Chat/ChatContext.d.ts.map +1 -1
  47. package/dist/Chat/ChatContext.js +16 -2
  48. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  49. package/dist/Chat/ChatDictationButton.js +1 -1
  50. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  51. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  52. package/dist/Chat/ChatLayoutScrollButton.js +4 -4
  53. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  54. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  55. package/dist/Chat/ChatSendButton.js +7 -1
  56. package/dist/Chat/ChatToolCalls.d.ts +5 -1
  57. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  58. package/dist/Chat/ChatToolCalls.js +18 -9
  59. package/dist/Chat/index.d.ts +2 -1
  60. package/dist/Chat/index.d.ts.map +1 -1
  61. package/dist/Chat/index.js +1 -1
  62. package/dist/Chat/useChatStreamScroll.d.ts +2 -1
  63. package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
  64. package/dist/Chat/useChatStreamScroll.js +22 -8
  65. package/dist/Chat/useSpeechRecognition.d.ts +0 -1
  66. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  67. package/dist/Chat/useSpeechRecognition.js +1 -1
  68. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  69. package/dist/CheckboxInput/CheckboxInput.js +1 -1
  70. package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
  71. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  72. package/dist/CheckboxList/CheckboxListItem.js +11 -1
  73. package/dist/ClickableCard/ClickableCard.d.ts +9 -2
  74. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  75. package/dist/ClickableCard/ClickableCard.js +5 -2
  76. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  77. package/dist/CodeBlock/CodeBlock.js +8 -1
  78. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  79. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  80. package/dist/CommandPalette/CommandPalette.js +3 -1
  81. package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
  82. package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
  83. package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
  84. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  85. package/dist/CommandPalette/CommandPaletteInput.js +6 -1
  86. package/dist/DateInput/DateInput.d.ts +47 -1
  87. package/dist/DateInput/DateInput.d.ts.map +1 -1
  88. package/dist/DateInput/DateInput.js +26 -2
  89. package/dist/DateInput/index.d.ts +1 -1
  90. package/dist/DateInput/index.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  92. package/dist/DateTimeInput/DateTimeInput.js +10 -1
  93. package/dist/Dialog/Dialog.d.ts +3 -0
  94. package/dist/Dialog/Dialog.d.ts.map +1 -1
  95. package/dist/Dialog/Dialog.js +57 -6
  96. package/dist/Dialog/DialogContext.d.ts +7 -0
  97. package/dist/Dialog/DialogContext.d.ts.map +1 -1
  98. package/dist/Dialog/DialogContext.js +2 -2
  99. package/dist/Dialog/DialogHeader.d.ts +5 -2
  100. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  101. package/dist/Dialog/DialogHeader.js +6 -1
  102. package/dist/Divider/Divider.js +1 -1
  103. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
  104. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  105. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +1 -2
  106. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
  107. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  108. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
  109. package/dist/Field/Field.d.ts.map +1 -1
  110. package/dist/Field/Field.js +2 -3
  111. package/dist/Field/FieldLabel.d.ts +1 -1
  112. package/dist/Field/FieldLabel.d.ts.map +1 -1
  113. package/dist/Field/FieldLabel.js +42 -15
  114. package/dist/FieldStatus/FieldStatus.d.ts +8 -0
  115. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  116. package/dist/FieldStatus/FieldStatus.js +22 -4
  117. package/dist/FileInput/FileInput.d.ts.map +1 -1
  118. package/dist/FileInput/FileInput.js +10 -2
  119. package/dist/HoverCard/HoverCard.d.ts +9 -1
  120. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  121. package/dist/HoverCard/HoverCard.js +2 -0
  122. package/dist/HoverCard/useHoverCard.d.ts +8 -0
  123. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  124. package/dist/HoverCard/useHoverCard.js +7 -2
  125. package/dist/Icon/Icon.d.ts +7 -2
  126. package/dist/Icon/Icon.d.ts.map +1 -1
  127. package/dist/Item/Item.d.ts +6 -1
  128. package/dist/Item/Item.d.ts.map +1 -1
  129. package/dist/Item/Item.js +22 -1
  130. package/dist/Layer/useLayer.d.ts +6 -0
  131. package/dist/Layer/useLayer.d.ts.map +1 -1
  132. package/dist/Layer/useLayer.js +2 -0
  133. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  134. package/dist/MobileNav/MobileNav.js +6 -1
  135. package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
  136. package/dist/MobileNav/MobileNavToggle.js +4 -0
  137. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  138. package/dist/MultiSelector/MultiSelector.js +39 -12
  139. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  140. package/dist/MultiSelector/hooks.js +16 -0
  141. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  142. package/dist/Outline/Outline.d.ts +0 -1
  143. package/dist/Outline/Outline.d.ts.map +1 -1
  144. package/dist/Outline/Outline.js +0 -1
  145. package/dist/OverflowList/OverflowList.d.ts +20 -3
  146. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  147. package/dist/OverflowList/OverflowList.js +29 -4
  148. package/dist/Popover/Popover.d.ts.map +1 -1
  149. package/dist/Popover/Popover.js +3 -2
  150. package/dist/Popover/usePopover.d.ts.map +1 -1
  151. package/dist/Popover/usePopover.js +3 -9
  152. package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
  153. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  154. package/dist/SelectableCard/SelectableCard.d.ts +9 -2
  155. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  156. package/dist/SelectableCard/SelectableCard.js +16 -13
  157. package/dist/Selector/Selector.d.ts.map +1 -1
  158. package/dist/Selector/Selector.js +4 -2
  159. package/dist/Selector/hooks.d.ts.map +1 -1
  160. package/dist/Selector/hooks.js +16 -0
  161. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  162. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  163. package/dist/SideNav/SideNavHeading.js +21 -8
  164. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  165. package/dist/Slider/Slider.d.ts.map +1 -1
  166. package/dist/Slider/Slider.js +19 -2
  167. package/dist/Stack/stack.stylex.d.ts +9 -9
  168. package/dist/Table/BaseTable.d.ts.map +1 -1
  169. package/dist/Table/BaseTable.js +3 -2
  170. package/dist/Table/index.d.ts +2 -0
  171. package/dist/Table/index.d.ts.map +1 -1
  172. package/dist/Table/index.js +1 -0
  173. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  174. package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
  175. package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
  176. package/dist/Table/plugins/rowStatus/index.js +3 -0
  177. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
  178. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
  179. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
  180. package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
  181. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  182. package/dist/Table/plugins/selection/useTableSelection.js +4 -1
  183. package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
  184. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  185. package/dist/Table/plugins/tree/useTableTreeData.js +87 -0
  186. package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
  187. package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
  188. package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
  189. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  190. package/dist/Table/useBaseTablePlugins.js +5 -3
  191. package/dist/Thumbnail/Thumbnail.d.ts +26 -5
  192. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  193. package/dist/Thumbnail/Thumbnail.js +97 -54
  194. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
  195. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
  196. package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
  197. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  198. package/dist/TimeInput/TimeInput.js +15 -4
  199. package/dist/Timestamp/Timestamp.d.ts +3 -1
  200. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  201. package/dist/Timestamp/Timestamp.js +8 -6
  202. package/dist/Toast/useToast.d.ts.map +1 -1
  203. package/dist/Toast/useToast.js +2 -5
  204. package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
  205. package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
  206. package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
  207. package/dist/Tokenizer/Tokenizer.d.ts +1 -1
  208. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  209. package/dist/Tokenizer/Tokenizer.js +16 -4
  210. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  211. package/dist/TopNav/TopNavHeading.js +18 -8
  212. package/dist/TopNav/TopNavMegaMenu.js +10 -4
  213. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
  214. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  215. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
  216. package/dist/TopNav/TopNavMenu.d.ts +2 -1
  217. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  218. package/dist/TopNav/TopNavMenu.js +68 -6
  219. package/dist/TreeList/TreeList.d.ts +12 -3
  220. package/dist/TreeList/TreeList.d.ts.map +1 -1
  221. package/dist/TreeList/TreeList.js +2 -0
  222. package/dist/TreeList/TreeListBranches.d.ts +5 -0
  223. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  224. package/dist/TreeList/TreeListBranches.js +10 -4
  225. package/dist/TreeList/TreeListItem.d.ts +8 -2
  226. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  227. package/dist/TreeList/TreeListItem.js +27 -7
  228. package/dist/TreeList/TreeListTypes.d.ts +25 -1
  229. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  230. package/dist/TreeList/index.d.ts +2 -2
  231. package/dist/TreeList/index.d.ts.map +1 -1
  232. package/dist/astryx.css +28 -18
  233. package/dist/astryx.umd.js +51 -51
  234. package/dist/astryx.umd.js.map +4 -4
  235. package/dist/authoring/doc.d.ts.map +1 -1
  236. package/dist/docs-types.d.ts +8 -0
  237. package/dist/docs-types.d.ts.map +1 -1
  238. package/dist/hooks/computeOverflow.d.ts +47 -0
  239. package/dist/hooks/computeOverflow.d.ts.map +1 -0
  240. package/dist/hooks/computeOverflow.js +213 -0
  241. package/dist/hooks/index.d.ts +1 -0
  242. package/dist/hooks/index.d.ts.map +1 -1
  243. package/dist/hooks/index.js +2 -1
  244. package/dist/hooks/useDevWarning.d.ts +18 -0
  245. package/dist/hooks/useDevWarning.d.ts.map +1 -0
  246. package/dist/hooks/useDevWarning.js +49 -0
  247. package/dist/hooks/useOverflow.d.ts +19 -0
  248. package/dist/hooks/useOverflow.d.ts.map +1 -1
  249. package/dist/hooks/useOverflow.js +36 -25
  250. package/dist/i18n/resolve.d.ts.map +1 -1
  251. package/dist/i18n/resolve.js +7 -18
  252. package/dist/theme/Theme.d.ts.map +1 -1
  253. package/dist/theme/Theme.js +2 -7
  254. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  255. package/dist/theme/generateThemeRules.js +51 -0
  256. package/dist/theme/hct.d.ts +0 -1
  257. package/dist/theme/hct.d.ts.map +1 -1
  258. package/dist/theme/hct.js +1 -1
  259. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  260. package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
  261. package/dist/utils/devWarning.d.ts +42 -0
  262. package/dist/utils/devWarning.d.ts.map +1 -0
  263. package/dist/utils/devWarning.js +88 -0
  264. package/dist/utils/index.d.ts +3 -1
  265. package/dist/utils/index.d.ts.map +1 -1
  266. package/dist/utils/index.js +3 -2
  267. package/dist/utils/plainDate.d.ts +30 -0
  268. package/dist/utils/plainDate.d.ts.map +1 -1
  269. package/dist/utils/plainDate.js +53 -0
  270. package/dist/utils/types.d.ts +13 -0
  271. package/dist/utils/types.d.ts.map +1 -1
  272. package/locales/en.json +24 -0
  273. package/locales/fr-FR.json +14 -0
  274. package/locales/pseudo.json +18 -0
  275. package/package.json +1 -1
  276. package/src/AppShell/AppShell.tsx +6 -0
  277. package/src/AppShell/AppShellMobileContext.tsx +8 -0
  278. package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
  279. package/src/Avatar/Avatar.doc.mjs +15 -3
  280. package/src/Avatar/Avatar.test.tsx +156 -1
  281. package/src/Avatar/Avatar.tsx +96 -4
  282. package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
  283. package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
  284. package/src/Avatar/AvatarStatusDot.tsx +178 -21
  285. package/src/Banner/Banner.doc.mjs +9 -0
  286. package/src/Banner/Banner.test.tsx +30 -0
  287. package/src/Banner/Banner.tsx +47 -3
  288. package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
  289. package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
  290. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
  291. package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
  292. package/src/Breadcrumbs/index.ts +27 -0
  293. package/src/Button/Button.doc.mjs +9 -0
  294. package/src/Button/Button.test.tsx +49 -0
  295. package/src/Button/Button.tsx +25 -1
  296. package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
  297. package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
  298. package/src/ButtonGroup/ButtonGroup.tsx +32 -0
  299. package/src/Calendar/Calendar.doc.mjs +12 -1
  300. package/src/Calendar/Calendar.test.tsx +193 -0
  301. package/src/Calendar/Calendar.tsx +38 -16
  302. package/src/Calendar/dayCellUtils.test.ts +5 -0
  303. package/src/Calendar/dayCellUtils.ts +1 -1
  304. package/src/Card/Card.doc.mjs +9 -0
  305. package/src/Card/Card.test.tsx +21 -3
  306. package/src/Card/Card.tsx +35 -2
  307. package/src/Carousel/Carousel.doc.mjs +1 -0
  308. package/src/Carousel/Carousel.test.tsx +53 -0
  309. package/src/Carousel/Carousel.tsx +34 -4
  310. package/src/Chat/ChatComposer.doc.mjs +12 -3
  311. package/src/Chat/ChatComposer.test.tsx +115 -0
  312. package/src/Chat/ChatComposer.tsx +73 -9
  313. package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
  314. package/src/Chat/ChatComposerDrawer.tsx +11 -1
  315. package/src/Chat/ChatComposerInput.doc.mjs +7 -0
  316. package/src/Chat/ChatComposerInput.test.tsx +103 -0
  317. package/src/Chat/ChatComposerInput.tsx +49 -3
  318. package/src/Chat/ChatContext.tsx +37 -10
  319. package/src/Chat/ChatDictationButton.tsx +4 -1
  320. package/src/Chat/ChatLayout.tsx +3 -1
  321. package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
  322. package/src/Chat/ChatMessageMetadata.tsx +1 -2
  323. package/src/Chat/ChatSendButton.tsx +11 -1
  324. package/src/Chat/ChatToolCalls.test.tsx +64 -0
  325. package/src/Chat/ChatToolCalls.tsx +25 -4
  326. package/src/Chat/index.ts +5 -1
  327. package/src/Chat/useChatStreamScroll.test.tsx +49 -0
  328. package/src/Chat/useChatStreamScroll.ts +27 -10
  329. package/src/Chat/useSpeechRecognition.ts +1 -1
  330. package/src/Chat/useTriggerMenu.tsx +3 -1
  331. package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
  332. package/src/CheckboxInput/CheckboxInput.tsx +1 -1
  333. package/src/CheckboxList/CheckboxList.test.tsx +81 -3
  334. package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
  335. package/src/CheckboxList/CheckboxListItem.tsx +41 -5
  336. package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
  337. package/src/ClickableCard/ClickableCard.test.tsx +34 -0
  338. package/src/ClickableCard/ClickableCard.tsx +13 -3
  339. package/src/CodeBlock/CodeBlock.test.tsx +56 -0
  340. package/src/CodeBlock/CodeBlock.tsx +9 -1
  341. package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
  342. package/src/CommandPalette/CommandPalette.tsx +3 -1
  343. package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
  344. package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
  345. package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
  346. package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
  347. package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
  348. package/src/ContextMenu/ContextMenu.test.tsx +193 -0
  349. package/src/DateInput/DateInput.doc.mjs +16 -0
  350. package/src/DateInput/DateInput.test.tsx +108 -0
  351. package/src/DateInput/DateInput.tsx +68 -3
  352. package/src/DateInput/index.ts +1 -0
  353. package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
  354. package/src/DateTimeInput/DateTimeInput.tsx +14 -2
  355. package/src/Dialog/Dialog.doc.mjs +2 -2
  356. package/src/Dialog/Dialog.test.tsx +77 -4
  357. package/src/Dialog/Dialog.tsx +89 -5
  358. package/src/Dialog/DialogContext.ts +9 -2
  359. package/src/Dialog/DialogHeader.doc.mjs +2 -2
  360. package/src/Dialog/DialogHeader.tsx +9 -2
  361. package/src/Divider/Divider.tsx +2 -2
  362. package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
  363. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -2
  364. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
  365. package/src/Field/Field.test.tsx +57 -12
  366. package/src/Field/Field.tsx +6 -5
  367. package/src/Field/FieldLabel.tsx +8 -0
  368. package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
  369. package/src/FieldStatus/FieldStatus.test.tsx +78 -40
  370. package/src/FieldStatus/FieldStatus.tsx +22 -4
  371. package/src/FileInput/FileInput.test.tsx +52 -3
  372. package/src/FileInput/FileInput.tsx +13 -2
  373. package/src/HoverCard/HoverCard.doc.mjs +13 -0
  374. package/src/HoverCard/HoverCard.test.tsx +21 -2
  375. package/src/HoverCard/HoverCard.tsx +11 -0
  376. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  377. package/src/HoverCard/useHoverCard.tsx +24 -2
  378. package/src/Icon/Icon.doc.mjs +3 -2
  379. package/src/Icon/Icon.tsx +7 -2
  380. package/src/IconButton/IconButton.doc.mjs +8 -0
  381. package/src/IconButton/IconButton.test.tsx +15 -18
  382. package/src/Item/Item.test.tsx +40 -18
  383. package/src/Item/Item.tsx +38 -2
  384. package/src/Layer/useLayer.tsx +8 -0
  385. package/src/List/List.test.tsx +9 -8
  386. package/src/MobileNav/MobileNav.tsx +12 -1
  387. package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
  388. package/src/MobileNav/MobileNavToggle.tsx +9 -1
  389. package/src/MultiSelector/MultiSelector.doc.mjs +4 -2
  390. package/src/MultiSelector/MultiSelector.test.tsx +172 -3
  391. package/src/MultiSelector/MultiSelector.tsx +55 -12
  392. package/src/MultiSelector/hooks.ts +17 -0
  393. package/src/NumberInput/NumberInput.test.tsx +11 -7
  394. package/src/NumberInput/NumberInput.tsx +1 -2
  395. package/src/Outline/Outline.tsx +0 -1
  396. package/src/OverflowList/OverflowList.doc.mjs +39 -6
  397. package/src/OverflowList/OverflowList.test.tsx +111 -0
  398. package/src/OverflowList/OverflowList.tsx +48 -8
  399. package/src/Popover/Popover.tsx +7 -4
  400. package/src/Popover/usePopover.tsx +9 -13
  401. package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
  402. package/src/PowerSearch/PowerSearch.test.tsx +20 -0
  403. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
  404. package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
  405. package/src/PowerSearch/usePowerSearchSource.ts +1 -2
  406. package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
  407. package/src/SelectableCard/SelectableCard.test.tsx +46 -4
  408. package/src/SelectableCard/SelectableCard.tsx +29 -16
  409. package/src/Selector/Selector.test.tsx +69 -0
  410. package/src/Selector/Selector.tsx +5 -1
  411. package/src/Selector/hooks.ts +17 -0
  412. package/src/SideNav/SideNav.test.tsx +119 -3
  413. package/src/SideNav/SideNavCollapseButton.tsx +6 -1
  414. package/src/SideNav/SideNavHeading.tsx +24 -8
  415. package/src/SideNav/SideNavItem.tsx +5 -1
  416. package/src/Slider/Slider.test.tsx +75 -2
  417. package/src/Slider/Slider.tsx +21 -5
  418. package/src/Switch/Switch.test.tsx +32 -1
  419. package/src/Table/BaseTable.tsx +3 -5
  420. package/src/Table/index.ts +5 -0
  421. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
  422. package/src/Table/plugins/rowStatus/index.ts +7 -0
  423. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
  424. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
  425. package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
  426. package/src/Table/plugins/selection/useTableSelection.tsx +19 -1
  427. package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
  428. package/src/Table/plugins/tree/useTableTreeData.tsx +128 -1
  429. package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
  430. package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
  431. package/src/Table/useBaseTablePlugins.ts +10 -6
  432. package/src/Table/useTableRowStatus.doc.mjs +30 -0
  433. package/src/Table/useTableSelection.doc.mjs +65 -14
  434. package/src/Table/useTableTreeData.doc.mjs +29 -0
  435. package/src/Table/useTableTreeState.doc.mjs +2 -2
  436. package/src/TextArea/TextArea.test.tsx +9 -1
  437. package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
  438. package/src/Thumbnail/Thumbnail.test.tsx +98 -7
  439. package/src/Thumbnail/Thumbnail.tsx +141 -41
  440. package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
  441. package/src/TimeInput/TimeInput.test.tsx +76 -1
  442. package/src/TimeInput/TimeInput.tsx +19 -6
  443. package/src/Timestamp/Timestamp.doc.mjs +4 -4
  444. package/src/Timestamp/Timestamp.test.tsx +32 -0
  445. package/src/Timestamp/Timestamp.tsx +28 -8
  446. package/src/Toast/useToast.tsx +7 -8
  447. package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
  448. package/src/Tokenizer/Tokenizer.doc.mjs +15 -1
  449. package/src/Tokenizer/Tokenizer.test.tsx +183 -2
  450. package/src/Tokenizer/Tokenizer.tsx +16 -4
  451. package/src/TopNav/TopNav.test.tsx +125 -1
  452. package/src/TopNav/TopNavHeading.tsx +24 -8
  453. package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
  454. package/src/TopNav/TopNavMegaMenu.tsx +10 -4
  455. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
  456. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
  457. package/src/TopNav/TopNavMenu.test.tsx +118 -4
  458. package/src/TopNav/TopNavMenu.tsx +83 -5
  459. package/src/TreeList/TreeList.doc.mjs +22 -0
  460. package/src/TreeList/TreeList.test.tsx +232 -0
  461. package/src/TreeList/TreeList.tsx +18 -2
  462. package/src/TreeList/TreeListBranches.tsx +16 -2
  463. package/src/TreeList/TreeListItem.tsx +51 -11
  464. package/src/TreeList/TreeListTypes.ts +27 -1
  465. package/src/TreeList/index.ts +2 -2
  466. package/src/authoring/doc.ts +1 -3
  467. package/src/docs-types.ts +5 -0
  468. package/src/hooks/computeOverflow.test.ts +422 -0
  469. package/src/hooks/computeOverflow.ts +290 -0
  470. package/src/hooks/index.ts +2 -0
  471. package/src/hooks/useDevWarning.test.tsx +45 -0
  472. package/src/hooks/useDevWarning.ts +54 -0
  473. package/src/hooks/useOverflow.test.ts +96 -4
  474. package/src/hooks/useOverflow.ts +74 -33
  475. package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
  476. package/src/i18n/resolve.ts +9 -21
  477. package/src/theme/Theme.tsx +11 -14
  478. package/src/theme/generateThemeRules.test.ts +65 -0
  479. package/src/theme/generateThemeRules.ts +56 -0
  480. package/src/theme/hct.ts +1 -1
  481. package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
  482. package/src/utils/devWarning.test.ts +56 -0
  483. package/src/utils/devWarning.ts +102 -0
  484. package/src/utils/index.ts +6 -0
  485. package/src/utils/plainDate.test.ts +22 -0
  486. package/src/utils/plainDate.ts +61 -0
  487. package/src/utils/types.ts +14 -0
@@ -7,14 +7,22 @@ export const docs = {
7
7
  subComponentOf: 'CheckboxList',
8
8
  displayName: 'Checkbox List Item',
9
9
  isHiddenFromOverview: true,
10
- description: 'Individual checkbox item with label, description, and end content slot. Works in collection mode (inside CheckboxList) or standalone mode (inside List).',
10
+ description:
11
+ 'Individual checkbox item with label, description, and end content slot. Works in collection mode (inside CheckboxList) or standalone mode (inside List).',
11
12
  props: [
12
13
  {
13
14
  name: 'label',
14
- type: 'string',
15
- description: 'Primary text label for the item.',
15
+ type: 'ReactNode',
16
+ description:
17
+ 'Primary text label for the item. A plain string names the checkbox automatically; a rich (ReactNode) label should be paired with aria-label so screen readers get a concise name.',
16
18
  required: true,
17
19
  },
20
+ {
21
+ name: 'aria-label',
22
+ type: 'string',
23
+ description:
24
+ 'Plain-text accessible name for the checkbox when label is a ReactNode. Applied to the checkbox control. Without it, rich-label items all announce as the generic "Checkbox" to screen readers.',
25
+ },
18
26
  {
19
27
  name: 'value',
20
28
  type: 'string',
@@ -69,13 +77,24 @@ export const docs = {
69
77
  description: 'Direct check handler (standalone mode only).',
70
78
  },
71
79
  ],
80
+ examples: [
81
+ {
82
+ label: 'Rich label with an accessible name',
83
+ code: `<CheckboxListItem
84
+ label={<span>Pro plan <Badge label="Recommended" /></span>}
85
+ aria-label="Pro plan"
86
+ value="pro"
87
+ />`,
88
+ },
89
+ ],
72
90
  };
73
91
 
74
92
  export const docsZh = {
75
93
  name: 'CheckboxListItem',
76
94
  isHiddenFromOverview: true,
77
95
  displayName: 'Checkbox List Item',
78
- description: '单个复选框选项,包含标签、描述和尾部内容插槽。可在集合模式或独立模式下使用。',
96
+ description:
97
+ '单个复选框选项,包含标签、描述和尾部内容插槽。可在集合模式或独立模式下使用。',
79
98
  props: [
80
99
  {
81
100
  name: 'label',
@@ -83,6 +102,12 @@ export const docsZh = {
83
102
  description: '选项的主要文本标签。',
84
103
  required: true,
85
104
  },
105
+ {
106
+ name: 'aria-label',
107
+ type: 'string',
108
+ description:
109
+ '当 label 是 ReactNode 时,复选框的纯文本无障碍名称。缺少它时,富标签选项都会向屏幕阅读器播报为通用的 "Checkbox"。',
110
+ },
86
111
  {
87
112
  name: 'value',
88
113
  type: 'string',
@@ -128,9 +153,12 @@ export const docsDense = {
128
153
  name: 'CheckboxListItem',
129
154
  isHiddenFromOverview: true,
130
155
  displayName: 'Checkbox List Item',
131
- description: 'Individual checkbox item w/ label, description, end content slot.',
156
+ description:
157
+ 'Individual checkbox item w/ label, description, end content slot.',
132
158
  propDescriptions: {
133
159
  label: 'Primary text label for item.',
160
+ 'aria-label':
161
+ 'Plain-text checkbox name when label is a ReactNode. Without it, rich-label items all announce as "Checkbox".',
134
162
  value: 'Identity key (required inside CheckboxList).',
135
163
  description: 'Secondary text below label.',
136
164
  endContent: 'Content rendered after label area.',
@@ -22,6 +22,7 @@ import type {StyleXStyles} from '@stylexjs/stylex';
22
22
  import {colorVars} from '../theme/tokens.stylex';
23
23
  import type {BaseProps} from '../BaseProps';
24
24
  import {composeEventHandlers} from '../utils';
25
+ import {useDevWarning} from '../hooks/useDevWarning';
25
26
  import {CheckboxInput} from '../CheckboxInput/CheckboxInput';
26
27
  import {ListItem} from '../List/ListItem';
27
28
  import {ListContext} from '../List/ListContext';
@@ -51,6 +52,25 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
51
52
  * child components control their own text behavior).
52
53
  */
53
54
  label: ReactNode;
55
+ /**
56
+ * Plain-text accessible name for the checkbox when `label` is a ReactNode.
57
+ *
58
+ * A string `label` names the checkbox automatically. A rich (ReactNode)
59
+ * `label` cannot, so pass a concise string equivalent via the standard
60
+ * `aria-label` — otherwise the checkbox falls back to the generic name
61
+ * "Checkbox" and every rich-label item in a list announces identically to
62
+ * screen readers. Applied to the checkbox control, not the row.
63
+ *
64
+ * @example
65
+ * ```
66
+ * <CheckboxListItem
67
+ * label={<span>Pro plan <Badge label="Recommended" /></span>}
68
+ * aria-label="Pro plan"
69
+ * value="pro"
70
+ * />
71
+ * ```
72
+ */
73
+ 'aria-label'?: string;
54
74
  /**
55
75
  * Identity key for collection mode (REQUIRED inside CheckboxList).
56
76
  * Throws a runtime error if missing when used inside CheckboxList.
@@ -119,6 +139,7 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
119
139
  */
120
140
  export function CheckboxListItem({
121
141
  label,
142
+ 'aria-label': ariaLabel,
122
143
  value,
123
144
  description,
124
145
  endContent,
@@ -142,6 +163,25 @@ export function CheckboxListItem({
142
163
  );
143
164
  }
144
165
 
166
+ // Accessible name for the (visually hidden) checkbox label. A string
167
+ // `label` names it directly; a rich label needs `aria-label`.
168
+ const checkboxLabel =
169
+ ariaLabel ??
170
+ (typeof label === 'string'
171
+ ? label
172
+ : t('@astryx.checkboxList.item.checkbox'));
173
+
174
+ // Dev-time guardrail: a rich label without `aria-label` leaves the
175
+ // checkbox with the generic name "Checkbox".
176
+ useDevWarning(
177
+ 'CheckboxListItem',
178
+ '`label` is a ReactNode, so the checkbox falls ' +
179
+ 'back to the generic accessible name "Checkbox". Pass ' +
180
+ '`aria-label` with a concise string equivalent of the visible ' +
181
+ 'label so screen readers can tell items apart.',
182
+ typeof label !== 'string' && ariaLabel == null,
183
+ );
184
+
145
185
  // Density from list context for checkbox sizing
146
186
  const listCtx = use(ListContext);
147
187
  const density = listCtx?.density ?? 'balanced';
@@ -226,11 +266,7 @@ export function CheckboxListItem({
226
266
  style={style}
227
267
  startContent={
228
268
  <CheckboxInput
229
- label={
230
- typeof label === 'string'
231
- ? label
232
- : t('@astryx.checkboxList.item.checkbox')
233
- }
269
+ label={checkboxLabel}
234
270
  isLabelHidden
235
271
  value={resolvedChecked}
236
272
  onChange={() => handleToggle()}
@@ -28,6 +28,7 @@ export const docs = {
28
28
  {name: 'children', type: 'ReactNode', description: 'Card content.'},
29
29
  {name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: 'Inner padding.', default: '4'},
30
30
  {name: 'variant', type: "'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow'", description: 'Background color variant.', default: "'default'"},
31
+ {name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: 'Resting shadow depth. Often raised to signal the whole card is clickable.', default: "'none'"},
31
32
  {name: 'width', type: 'SizeValue', description: 'Card width.'},
32
33
  {name: 'height', type: 'SizeValue', description: 'Card height.'},
33
34
  {name: 'maxWidth', type: 'SizeValue', description: 'Maximum card width.'},
@@ -73,6 +74,7 @@ export const docsDense = {
73
74
  isDisabled: 'disables card',
74
75
  padding: 'inner padding',
75
76
  variant: 'background color variant',
77
+ elevation: 'resting shadow depth: none|low|med|high; often raised to signal clickability',
76
78
  width: 'card width',
77
79
  height: 'card height',
78
80
  maxWidth: 'max card width',
@@ -106,4 +106,38 @@ describe('ClickableCard', () => {
106
106
  const link = screen.getByRole('link', {name: 'Disabled link'});
107
107
  expect(link).toHaveAttribute('aria-disabled', 'true');
108
108
  });
109
+
110
+ describe('elevation', () => {
111
+ it('forwards a distinct elevation class to the card for each level', () => {
112
+ const classFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
113
+ const {container} = render(
114
+ <ClickableCard label="Card" elevation={elevation}>
115
+ Content
116
+ </ClickableCard>,
117
+ );
118
+ return container.firstElementChild!.className;
119
+ };
120
+ const classes = new Set([
121
+ classFor('none'),
122
+ classFor('low'),
123
+ classFor('med'),
124
+ classFor('high'),
125
+ ]);
126
+ expect(classes.size).toBe(4);
127
+ });
128
+
129
+ it('defaults to flat (elevation none)', () => {
130
+ const {container: def} = render(
131
+ <ClickableCard label="Card">Content</ClickableCard>,
132
+ );
133
+ const {container: none} = render(
134
+ <ClickableCard label="Card" elevation="none">
135
+ Content
136
+ </ClickableCard>,
137
+ );
138
+ expect(def.firstElementChild!.className).toBe(
139
+ none.firstElementChild!.className,
140
+ );
141
+ });
142
+ });
109
143
  });
@@ -14,6 +14,7 @@
14
14
  * - /apps/storybook/stories/ClickableCard.stories.tsx (storybook stories)
15
15
  * - /packages/cli/templates/blocks/components/Card/ClickableCardShowcase.tsx (showcase block)
16
16
  * - /packages/cli/templates/blocks/components/Card/ClickableCardWithNestedButton.tsx (block)
17
+ * - /packages/cli/templates/blocks/components/Card/ClickableCardElevated.tsx (block)
17
18
  *
18
19
  * Composes Card for all visual styling (radius, padding, variants,
19
20
  * container tokens, theming). Adds an interactive wrapper with
@@ -37,7 +38,7 @@ import {
37
38
  durationVars,
38
39
  easeVars,
39
40
  } from '../theme/tokens.stylex';
40
- import type {SizeValue, SpacingStep} from '../utils/types';
41
+ import type {SizeValue, SpacingStep, Elevation} from '../utils/types';
41
42
  import {mergeProps, mergeRefs} from '../utils';
42
43
  import {Card} from '../Card/Card';
43
44
  import type {CardVariant} from '../Card/Card';
@@ -78,13 +79,13 @@ const styles = stylex.create({
78
79
  backgroundColor: 'transparent',
79
80
  },
80
81
  ':active::after': {
81
- backgroundColor: 'color-mix(in srgb, currentColor 10%, transparent)',
82
+ backgroundColor: colorVars['--color-overlay-pressed'],
82
83
  },
83
84
  },
84
85
  hoverOnPointer: {
85
86
  '@media (hover: hover)': {
86
87
  ':hover::after': {
87
- backgroundColor: 'color-mix(in srgb, currentColor 5%, transparent)',
88
+ backgroundColor: colorVars['--color-overlay-hover'],
88
89
  },
89
90
  },
90
91
  },
@@ -197,6 +198,13 @@ export interface ClickableCardProps extends BaseProps {
197
198
  */
198
199
  variant?: CardVariant;
199
200
 
201
+ /**
202
+ * Resting elevation — the shadow depth the card sits at. Often raised to
203
+ * signal that the whole card is clickable.
204
+ * @default 'none'
205
+ */
206
+ elevation?: Elevation;
207
+
200
208
  /** Width of the card. */
201
209
  width?: SizeValue;
202
210
 
@@ -253,6 +261,7 @@ export function ClickableCard({
253
261
  children,
254
262
  padding,
255
263
  variant = 'default',
264
+ elevation = 'none',
256
265
  width,
257
266
  height,
258
267
  maxWidth,
@@ -297,6 +306,7 @@ export function ClickableCard({
297
306
  maxWidth={maxWidth}
298
307
  padding={padding}
299
308
  variant={variant}
309
+ elevation={elevation}
300
310
  {...mergeProps(themeProps('clickable-card', {variant}), {
301
311
  className: classNameProp,
302
312
  style,
@@ -210,6 +210,62 @@ describe('CodeBlock', () => {
210
210
  expect(document.getElementById(controlsId as string)).not.toBeNull();
211
211
  });
212
212
 
213
+ it('makes the collapsed region inert so the scroll container is unreachable', () => {
214
+ render(
215
+ <CodeBlock
216
+ code={LONG_CODE}
217
+ language="javascript"
218
+ title="example"
219
+ isCollapsible
220
+ />,
221
+ );
222
+ const header = screen
223
+ .getAllByRole('button')
224
+ .find(el => el.hasAttribute('aria-expanded'))!;
225
+ const region = document.getElementById(
226
+ header.getAttribute('aria-controls') as string,
227
+ )!;
228
+ // Expanded: the region is not inert and the scroll container is reachable.
229
+ expect(region).not.toHaveAttribute('inert');
230
+
231
+ fireEvent.click(header);
232
+ expect(header).toHaveAttribute('aria-expanded', 'false');
233
+ // Collapsed: the wrapper is inert, so the keyboard-focusable scroll
234
+ // container (tabIndex=0) inside it drops out of the tab order and the
235
+ // accessibility tree instead of remaining an invisible tab stop.
236
+ expect(region).toHaveAttribute('inert');
237
+ const scrollContainer = screen.getByRole('group');
238
+ expect(scrollContainer.closest('[inert]')).toBe(region);
239
+ });
240
+
241
+ it('restores focusability of the scroll container after expanding again', () => {
242
+ render(
243
+ <CodeBlock
244
+ code={LONG_CODE}
245
+ language="javascript"
246
+ title="example"
247
+ isCollapsible
248
+ />,
249
+ );
250
+ const header = screen
251
+ .getAllByRole('button')
252
+ .find(el => el.hasAttribute('aria-expanded'))!;
253
+ const region = document.getElementById(
254
+ header.getAttribute('aria-controls') as string,
255
+ )!;
256
+ // Collapse, then expand again.
257
+ fireEvent.click(header);
258
+ expect(region).toHaveAttribute('inert');
259
+ fireEvent.click(header);
260
+ expect(header).toHaveAttribute('aria-expanded', 'true');
261
+ // Expanded again: inert is removed and the scroll container is a
262
+ // keyboard-focusable group once more.
263
+ expect(region).not.toHaveAttribute('inert');
264
+ const scrollContainer = screen.getByRole('group');
265
+ expect(scrollContainer.closest('[inert]')).toBeNull();
266
+ expect(scrollContainer).toHaveAttribute('tabindex', '0');
267
+ });
268
+
213
269
  it('applies a per-instance syntax theme via the syntaxTheme prop', () => {
214
270
  const {container} = render(
215
271
  <CodeBlock
@@ -807,7 +807,9 @@ export function CodeBlock({
807
807
  e.stopPropagation();
808
808
  void handleCopy();
809
809
  }}
810
- aria-label={copied ? t('@astryx.codeBlock.copied') : t('@astryx.codeBlock.copyCode')}
810
+ aria-label={
811
+ copied ? t('@astryx.codeBlock.copied') : t('@astryx.codeBlock.copyCode')
812
+ }
811
813
  {...stylex.props(
812
814
  styles.copyButton,
813
815
  !showHeader && styles.copyButtonAbsolute,
@@ -923,6 +925,12 @@ export function CodeBlock({
923
925
  {canCollapse ? (
924
926
  <div
925
927
  id={regionId}
928
+ // While collapsed, the region is only hidden visually (0fr grid
929
+ // row); inert also removes it from the tab order and accessibility
930
+ // tree so keyboard users cannot Tab into the invisible scroll
931
+ // container (tabIndex=0). aria-controls pointing at an inert
932
+ // element remains a valid, resolvable reference.
933
+ inert={isCollapsed ? true : undefined}
926
934
  {...stylex.props(
927
935
  styles.collapseGrid,
928
936
  isCollapsed && styles.collapseGridCollapsed,
@@ -145,6 +145,7 @@ export const docs = {
145
145
  {className: 'astryx-command-palette-empty'},
146
146
  {className: 'astryx-command-palette-footer'},
147
147
  {className: 'astryx-command-palette-group'},
148
+ {className: 'astryx-command-palette-group-heading'},
148
149
  {className: 'astryx-command-palette-input'},
149
150
  {className: 'astryx-command-palette-item'},
150
151
  {className: 'astryx-command-palette-list'},
@@ -268,6 +268,7 @@ export function CommandPalette<T extends SearchableItem = SearchableItem>({
268
268
  label: labelFromProps,
269
269
  width = 640,
270
270
  maxHeight = 480,
271
+ ...rest
271
272
  }: CommandPaletteProps<T>) {
272
273
  const t = useTranslator();
273
274
  const label = labelFromProps ?? t('@astryx.commandPalette.label');
@@ -527,7 +528,8 @@ export function CommandPalette<T extends SearchableItem = SearchableItem>({
527
528
  width={width}
528
529
  maxHeight={maxHeight}
529
530
  purpose="info"
530
- aria-label={label}>
531
+ aria-label={label}
532
+ {...rest}>
531
533
  <CommandPaletteContext value={contextValue}>
532
534
  <Layout
533
535
  defaultHasDividers
@@ -9,6 +9,8 @@
9
9
  import {describe, it, expect} from 'vitest';
10
10
  import {render, screen} from '@testing-library/react';
11
11
  import {CommandPaletteGroup} from './CommandPaletteGroup';
12
+ import {defineTheme} from '../theme/defineTheme';
13
+ import {generateThemeCSSFlat} from '../theme/generateThemeRules';
12
14
 
13
15
  describe('CommandPaletteGroup', () => {
14
16
  it('renders heading', () => {
@@ -51,4 +53,73 @@ describe('CommandPaletteGroup', () => {
51
53
  'true',
52
54
  );
53
55
  });
56
+
57
+ // ===========================================================================
58
+ // Heading theme target
59
+ // ===========================================================================
60
+
61
+ describe('heading theme target', () => {
62
+ it('renders the astryx-command-palette-group-heading target on the heading', () => {
63
+ render(
64
+ <CommandPaletteGroup heading="Suggestions">
65
+ <div>Item</div>
66
+ </CommandPaletteGroup>,
67
+ );
68
+ const heading = screen.getByText('Suggestions');
69
+
70
+ // The root carries `astryx-command-palette-group`; this is the stable
71
+ // handle on the heading itself, so a theme can style just the heading
72
+ // without a fragile structural selector.
73
+ expect(heading).toHaveClass('astryx-command-palette-group-heading');
74
+ });
75
+
76
+ it('keeps the heading target distinct from the group root target', () => {
77
+ render(
78
+ <CommandPaletteGroup heading="Suggestions">
79
+ <div>Item</div>
80
+ </CommandPaletteGroup>,
81
+ );
82
+ const root = screen.getByRole('group');
83
+ const heading = screen.getByText('Suggestions');
84
+
85
+ expect(root).toHaveClass('astryx-command-palette-group');
86
+ expect(root).not.toHaveClass('astryx-command-palette-group-heading');
87
+ expect(heading).not.toHaveClass('astryx-command-palette-group');
88
+ });
89
+
90
+ it('leaves the heading decorative (additive target only)', () => {
91
+ // The target adds a class and nothing else — the heading stays
92
+ // aria-hidden so grouping remains announced via the root's aria-label.
93
+ render(
94
+ <CommandPaletteGroup heading="Suggestions">
95
+ <div>Item</div>
96
+ </CommandPaletteGroup>,
97
+ );
98
+ expect(screen.getByText('Suggestions')).toHaveAttribute(
99
+ 'aria-hidden',
100
+ 'true',
101
+ );
102
+ });
103
+
104
+ it('exposes command-palette-group-heading as a themeable defineTheme target', () => {
105
+ // The generated CSS proves the target is reachable by a theme: jsdom
106
+ // cannot resolve the @layer cascade, so the DOM-class assertions above
107
+ // and this generation assertion together cover the seam.
108
+ const theme = defineTheme({
109
+ name: 'command-palette-group-heading-test',
110
+ components: {
111
+ 'command-palette-group-heading': {
112
+ base: {
113
+ paddingBlock: 'var(--spacing-2)',
114
+ fontWeight: 'var(--font-weight-bold)',
115
+ },
116
+ },
117
+ },
118
+ });
119
+ const css = generateThemeCSSFlat(theme);
120
+ expect(css).toContain('.astryx-command-palette-group-heading {');
121
+ expect(css).toContain('padding-block: var(--spacing-2)');
122
+ expect(css).toContain('font-weight: var(--font-weight-bold)');
123
+ });
124
+ });
54
125
  });
@@ -90,7 +90,18 @@ export function CommandPaletteGroup({
90
90
  style,
91
91
  )}
92
92
  {...props}>
93
- <div aria-hidden="true" {...stylex.props(styles.heading)}>
93
+ <div
94
+ aria-hidden="true"
95
+ {...mergeProps(
96
+ // Stable theme target for the group heading text. The root carries
97
+ // `astryx-command-palette-group`, but the heading itself had no
98
+ // handle, so a theme could only reach it through a fragile structural
99
+ // selector. This adds an `astryx-command-palette-group-heading` class
100
+ // so `defineTheme` can scope overrides (e.g. heading typography) to
101
+ // the heading alone.
102
+ themeProps('command-palette-group-heading'),
103
+ stylex.props(styles.heading),
104
+ )}>
94
105
  {heading}
95
106
  </div>
96
107
  {children}
@@ -7,7 +7,8 @@ export const docs = {
7
7
  subComponentOf: 'CommandPalette',
8
8
  displayName: 'Command Palette Input',
9
9
  isHiddenFromOverview: true,
10
- description: 'Search input slot. Auto-focuses on mount. Wires to command palette context when used inside CommandPalette.',
10
+ description:
11
+ 'Search input slot. Auto-focuses on mount. Wires to command palette context when used inside CommandPalette.',
11
12
  props: [
12
13
  {
13
14
  name: 'placeholder',
@@ -15,16 +16,24 @@ export const docs = {
15
16
  description: 'Placeholder text for the input.',
16
17
  default: "'Search...'",
17
18
  },
19
+ {
20
+ name: 'label',
21
+ type: 'string',
22
+ description:
23
+ 'Accessible label for the combobox input, announced by screen readers. Falls back to the placeholder text when omitted.',
24
+ },
18
25
  {
19
26
  name: 'hasAutoFocus',
20
27
  type: 'boolean',
21
- description: 'Auto-focus the input when mounted. Automatically disabled when inside an inline command palette.',
28
+ description:
29
+ 'Auto-focus the input when mounted. Automatically disabled when inside an inline command palette.',
22
30
  default: 'true',
23
31
  },
24
32
  {
25
33
  name: 'endContent',
26
34
  type: 'ReactNode',
27
- description: 'Content rendered at the trailing end of the input, after the spinner. Use for clear buttons or keyboard shortcut hints.',
35
+ description:
36
+ 'Content rendered at the trailing end of the input, after the spinner. Use for clear buttons or keyboard shortcut hints.',
28
37
  slotElements: [
29
38
  {
30
39
  __element: 'Icon',
@@ -44,17 +53,20 @@ export const docs = {
44
53
  {
45
54
  name: 'value',
46
55
  type: 'string',
47
- description: 'Search value. When omitted inside CommandPalette, reads from context.',
56
+ description:
57
+ 'Search value. When omitted inside CommandPalette, reads from context.',
48
58
  },
49
59
  {
50
60
  name: 'onValueChange',
51
61
  type: '(value: string) => void',
52
- description: 'Called when search value changes. When omitted inside CommandPalette, writes to context.',
62
+ description:
63
+ 'Called when search value changes. When omitted inside CommandPalette, writes to context.',
53
64
  },
54
65
  {
55
66
  name: 'xstyle',
56
67
  type: 'StyleXStyles',
57
- description: 'StyleX styles for layout customization. Must be a stylex.create() value.',
68
+ description:
69
+ 'StyleX styles for layout customization. Must be a stylex.create() value.',
58
70
  },
59
71
  ],
60
72
  playground: {
@@ -69,9 +81,11 @@ export const docsZh = {
69
81
  name: 'CommandPaletteInput',
70
82
  isHiddenFromOverview: true,
71
83
  displayName: 'Command Palette Input',
72
- description: '搜索输入插槽。挂载时自动聚焦。在 CommandPalette 内使用时连接到上下文。',
84
+ description:
85
+ '搜索输入插槽。挂载时自动聚焦。在 CommandPalette 内使用时连接到上下文。',
73
86
  propDescriptions: {
74
87
  placeholder: '输入框的占位文本。',
88
+ label: '组合框输入的无障碍标签,供屏幕阅读器朗读。省略时回退到占位文本。',
75
89
  hasAutoFocus: '挂载时自动聚焦输入框。内联命令面板中自动禁用。',
76
90
  endContent: '渲染在输入框末尾的内容,位于加载指示器之后。',
77
91
  value: '搜索值。在 CommandPalette 内省略时从上下文读取。',
@@ -84,13 +98,16 @@ export const docsDense = {
84
98
  name: 'CommandPaletteInput',
85
99
  isHiddenFromOverview: true,
86
100
  displayName: 'Command Palette Input',
87
- description: 'search input; auto-focus on mount; wires to context inside CommandPalette',
101
+ description:
102
+ 'search input; auto-focus on mount; wires to context inside CommandPalette',
88
103
  propDescriptions: {
89
104
  placeholder: 'input placeholder text',
105
+ label: 'accessible label for the combobox; falls back to placeholder',
90
106
  hasAutoFocus: 'auto-focus on mount; auto-disabled in inline mode',
91
107
  endContent: 'trailing content after spinner',
92
108
  value: 'search value; reads context when omitted inside palette',
93
- onValueChange: 'called on change; writes context when omitted inside palette',
109
+ onValueChange:
110
+ 'called on change; writes context when omitted inside palette',
94
111
  xstyle: 'StyleX layout styles; must be stylex.create() value',
95
112
  },
96
113
  };
@@ -32,6 +32,40 @@ describe('CommandPaletteInput', () => {
32
32
  expect(screen.getByRole('combobox')).toBeInTheDocument();
33
33
  });
34
34
 
35
+ it('has an accessible name by default', () => {
36
+ render(<CommandPaletteInput />);
37
+ expect(screen.getByRole('combobox')).toHaveAttribute(
38
+ 'aria-label',
39
+ 'Search…',
40
+ );
41
+ });
42
+
43
+ it('uses the label prop as the accessible name', () => {
44
+ render(<CommandPaletteInput label="Search commands" />);
45
+ const input = screen.getByRole('combobox');
46
+ expect(input).toHaveAttribute('aria-label', 'Search commands');
47
+ // The label prop does not affect the visible placeholder
48
+ expect(input).toHaveAttribute('placeholder', 'Search…');
49
+ });
50
+
51
+ it('falls back to a custom placeholder for the accessible name', () => {
52
+ render(<CommandPaletteInput placeholder="Type a command..." />);
53
+ expect(screen.getByRole('combobox')).toHaveAttribute(
54
+ 'aria-label',
55
+ 'Type a command...',
56
+ );
57
+ });
58
+
59
+ it('lets a consumer-passed aria-label override the default', () => {
60
+ render(
61
+ <CommandPaletteInput label="Search commands" aria-label="Custom name" />,
62
+ );
63
+ expect(screen.getByRole('combobox')).toHaveAttribute(
64
+ 'aria-label',
65
+ 'Custom name',
66
+ );
67
+ });
68
+
35
69
  it('calls onValueChange when typing', () => {
36
70
  const handleChange = vi.fn();
37
71
  render(<CommandPaletteInput onValueChange={handleChange} />);
@@ -109,6 +109,13 @@ export interface CommandPaletteInputProps extends Omit<
109
109
  */
110
110
  placeholder?: string;
111
111
 
112
+ /**
113
+ * Accessible label for the combobox input, announced by screen readers.
114
+ * Falls back to the placeholder text (`'Search…'` by default), since a
115
+ * placeholder alone is not a reliable accessible name.
116
+ */
117
+ label?: string;
118
+
112
119
  /**
113
120
  * Whether to auto-focus the input when mounted.
114
121
  * @default true
@@ -149,6 +156,7 @@ export function CommandPaletteInput({
149
156
  value: controlledValue,
150
157
  onValueChange,
151
158
  placeholder: placeholderFromProps,
159
+ label,
152
160
  hasAutoFocus = true,
153
161
  endContent,
154
162
  onChange,
@@ -215,6 +223,9 @@ export function CommandPaletteInput({
215
223
  ? ctx.getItemId(ctx.highlightedIndex)
216
224
  : undefined
217
225
  }
226
+ // A placeholder alone is not a reliable accessible name; give the
227
+ // combobox an explicit one (consumer aria-label via rest props wins).
228
+ aria-label={label ?? placeholder}
218
229
  placeholder={placeholder}
219
230
  value={value}
220
231
  data-autofocus={effectiveAutoFocus || undefined}