@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2

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 (631) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +131 -13
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +11 -5
  5. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  6. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  7. package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
  8. package/dist/Banner/Banner.d.ts +7 -0
  9. package/dist/Banner/Banner.d.ts.map +1 -1
  10. package/dist/Banner/Banner.js +9 -2
  11. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
  12. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  13. package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
  14. package/dist/Button/Button.d.ts +12 -2
  15. package/dist/Button/Button.d.ts.map +1 -1
  16. package/dist/Button/Button.js +53 -17
  17. package/dist/Calendar/Calendar.d.ts +5 -4
  18. package/dist/Calendar/Calendar.d.ts.map +1 -1
  19. package/dist/Calendar/Calendar.js +82 -43
  20. package/dist/Calendar/hooks/index.d.ts +0 -2
  21. package/dist/Calendar/hooks/index.d.ts.map +1 -1
  22. package/dist/Calendar/hooks/index.js +1 -2
  23. package/dist/Calendar/index.d.ts +3 -3
  24. package/dist/Calendar/index.d.ts.map +1 -1
  25. package/dist/Calendar/index.js +1 -1
  26. package/dist/Calendar/styles.d.ts +3 -9
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +3 -11
  29. package/dist/Carousel/Carousel.d.ts.map +1 -1
  30. package/dist/Carousel/Carousel.js +17 -3
  31. package/dist/Center/Center.d.ts +11 -1
  32. package/dist/Center/Center.d.ts.map +1 -1
  33. package/dist/Center/Center.js +9 -3
  34. package/dist/Chat/ChatMessageList.d.ts +14 -1
  35. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  36. package/dist/Chat/ChatMessageList.js +2 -0
  37. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  38. package/dist/Chat/useTriggerMenu.js +4 -1
  39. package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
  40. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  41. package/dist/CheckboxInput/CheckboxInput.js +51 -9
  42. package/dist/CheckboxList/CheckboxList.d.ts +13 -1
  43. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  44. package/dist/CheckboxList/CheckboxList.js +39 -9
  45. package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
  46. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  47. package/dist/Citation/Citation.d.ts.map +1 -1
  48. package/dist/Citation/Citation.js +3 -3
  49. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  50. package/dist/CodeBlock/CodeBlock.js +49 -37
  51. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  52. package/dist/CommandPalette/CommandPalette.js +5 -5
  53. package/dist/ContextMenu/ContextMenu.d.ts +4 -5
  54. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  55. package/dist/ContextMenu/ContextMenu.js +93 -11
  56. package/dist/DateInput/DateInput.d.ts +23 -1
  57. package/dist/DateInput/DateInput.d.ts.map +1 -1
  58. package/dist/DateInput/DateInput.js +59 -8
  59. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  60. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  61. package/dist/DateRangeInput/DateRangeInput.js +42 -9
  62. package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
  63. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  64. package/dist/DateTimeInput/DateTimeInput.js +78 -15
  65. package/dist/Dialog/Dialog.d.ts.map +1 -1
  66. package/dist/Dialog/Dialog.js +12 -0
  67. package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
  68. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  69. package/dist/DropdownMenu/DropdownMenu.js +42 -14
  70. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  71. package/dist/EmptyState/EmptyState.js +7 -1
  72. package/dist/Field/Field.d.ts +19 -2
  73. package/dist/Field/Field.d.ts.map +1 -1
  74. package/dist/Field/Field.js +4 -0
  75. package/dist/Field/FieldLabel.d.ts +21 -2
  76. package/dist/Field/FieldLabel.d.ts.map +1 -1
  77. package/dist/Field/FieldLabel.js +41 -26
  78. package/dist/FileInput/FileInput.d.ts +22 -1
  79. package/dist/FileInput/FileInput.d.ts.map +1 -1
  80. package/dist/FileInput/FileInput.js +56 -10
  81. package/dist/Grid/Grid.d.ts +11 -1
  82. package/dist/Grid/Grid.d.ts.map +1 -1
  83. package/dist/Grid/Grid.js +8 -0
  84. package/dist/HoverCard/HoverCard.d.ts +2 -2
  85. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  86. package/dist/HoverCard/HoverCard.js +18 -6
  87. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  88. package/dist/HoverCard/useHoverCard.js +7 -3
  89. package/dist/InputGroup/InputGroup.d.ts +2 -2
  90. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  91. package/dist/InputGroup/InputGroup.js +14 -5
  92. package/dist/InputGroup/InputGroupContext.d.ts +4 -0
  93. package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
  94. package/dist/InputGroup/InputGroupContext.js +2 -2
  95. package/dist/InputGroup/index.d.ts +1 -0
  96. package/dist/InputGroup/index.d.ts.map +1 -1
  97. package/dist/Kbd/Kbd.d.ts.map +1 -1
  98. package/dist/Kbd/Kbd.js +34 -2
  99. package/dist/Layer/anchorName.d.ts +20 -0
  100. package/dist/Layer/anchorName.d.ts.map +1 -0
  101. package/dist/Layer/anchorName.js +36 -0
  102. package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
  103. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  104. package/dist/Layer/layerAnimations.stylex.js +8 -4
  105. package/dist/Layer/useLayer.d.ts +29 -0
  106. package/dist/Layer/useLayer.d.ts.map +1 -1
  107. package/dist/Layer/useLayer.js +55 -11
  108. package/dist/Layout/Layout.d.ts +4 -11
  109. package/dist/Layout/Layout.d.ts.map +1 -1
  110. package/dist/Layout/Layout.js +10 -11
  111. package/dist/Layout/LayoutFooter.d.ts +2 -2
  112. package/dist/Layout/LayoutFooter.d.ts.map +1 -1
  113. package/dist/Layout/LayoutHeader.d.ts +2 -2
  114. package/dist/Layout/LayoutHeader.d.ts.map +1 -1
  115. package/dist/Layout/LayoutPanel.d.ts +2 -2
  116. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  117. package/dist/Layout/padding.stylex.d.ts +51 -0
  118. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  119. package/dist/Layout/padding.stylex.js +63 -0
  120. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  121. package/dist/Lightbox/Lightbox.js +4 -2
  122. package/dist/Link/Link.d.ts +17 -2
  123. package/dist/Link/Link.d.ts.map +1 -1
  124. package/dist/Link/Link.js +20 -9
  125. package/dist/Link/LinkProvider.d.ts +1 -0
  126. package/dist/Link/LinkProvider.d.ts.map +1 -1
  127. package/dist/Link/LinkProvider.js +1 -0
  128. package/dist/Markdown/Markdown.d.ts.map +1 -1
  129. package/dist/Markdown/Markdown.js +18 -3
  130. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  131. package/dist/MobileNav/MobileNav.js +13 -0
  132. package/dist/MoreMenu/MoreMenu.d.ts +1 -7
  133. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  134. package/dist/MoreMenu/MoreMenu.js +0 -2
  135. package/dist/MultiSelector/MultiSelector.d.ts +25 -2
  136. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  137. package/dist/MultiSelector/MultiSelector.js +103 -22
  138. package/dist/MultiSelector/hooks.d.ts +12 -1
  139. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  140. package/dist/MultiSelector/hooks.js +14 -1
  141. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  142. package/dist/NavMenu/NavHeadingMenu.js +34 -3
  143. package/dist/NumberInput/NumberInput.d.ts +23 -2
  144. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  145. package/dist/NumberInput/NumberInput.js +62 -12
  146. package/dist/Pagination/Pagination.d.ts +1 -1
  147. package/dist/Pagination/Pagination.d.ts.map +1 -1
  148. package/dist/Pagination/Pagination.js +46 -28
  149. package/dist/Popover/usePopover.d.ts +25 -2
  150. package/dist/Popover/usePopover.d.ts.map +1 -1
  151. package/dist/Popover/usePopover.js +18 -6
  152. package/dist/PowerSearch/PowerSearch.d.ts +11 -1
  153. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  154. package/dist/PowerSearch/PowerSearch.js +6 -1
  155. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  156. package/dist/ProgressBar/ProgressBar.js +3 -5
  157. package/dist/RadioList/RadioList.d.ts +20 -2
  158. package/dist/RadioList/RadioList.d.ts.map +1 -1
  159. package/dist/RadioList/RadioList.js +105 -9
  160. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  161. package/dist/RadioList/RadioListItem.js +13 -2
  162. package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
  163. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  164. package/dist/SegmentedControl/SegmentedControl.js +78 -44
  165. package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
  166. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  167. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  168. package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
  169. package/dist/Selector/Selector.d.ts +22 -1
  170. package/dist/Selector/Selector.d.ts.map +1 -1
  171. package/dist/Selector/Selector.js +84 -23
  172. package/dist/Selector/hooks.d.ts +8 -1
  173. package/dist/Selector/hooks.d.ts.map +1 -1
  174. package/dist/Selector/hooks.js +14 -1
  175. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  176. package/dist/SideNav/SideNavItem.js +1 -1
  177. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  178. package/dist/Skeleton/Skeleton.js +8 -2
  179. package/dist/Slider/Slider.d.ts +21 -0
  180. package/dist/Slider/Slider.d.ts.map +1 -1
  181. package/dist/Slider/Slider.js +38 -11
  182. package/dist/Spinner/Spinner.d.ts.map +1 -1
  183. package/dist/Spinner/Spinner.js +1 -1
  184. package/dist/Stack/Stack.d.ts +38 -23
  185. package/dist/Stack/Stack.d.ts.map +1 -1
  186. package/dist/Stack/Stack.js +25 -1
  187. package/dist/Stack/StackItem.d.ts +12 -23
  188. package/dist/Stack/StackItem.d.ts.map +1 -1
  189. package/dist/Stack/StackItem.js +8 -1
  190. package/dist/Switch/Switch.d.ts +23 -2
  191. package/dist/Switch/Switch.d.ts.map +1 -1
  192. package/dist/Switch/Switch.js +41 -11
  193. package/dist/TabList/Tab.d.ts.map +1 -1
  194. package/dist/TabList/Tab.js +6 -0
  195. package/dist/TabList/TabList.d.ts +16 -4
  196. package/dist/TabList/TabList.d.ts.map +1 -1
  197. package/dist/TabList/TabList.js +86 -10
  198. package/dist/TabList/TabListContext.d.ts +5 -0
  199. package/dist/TabList/TabListContext.d.ts.map +1 -1
  200. package/dist/TabList/TabListContext.js +5 -0
  201. package/dist/TabList/TabMenu.d.ts.map +1 -1
  202. package/dist/TabList/TabMenu.js +6 -1
  203. package/dist/Table/BaseTable.d.ts.map +1 -1
  204. package/dist/Table/BaseTable.js +38 -16
  205. package/dist/Table/Table.d.ts.map +1 -1
  206. package/dist/Table/Table.js +36 -7
  207. package/dist/Table/TableCell.d.ts +8 -1
  208. package/dist/Table/TableCell.d.ts.map +1 -1
  209. package/dist/Table/TableCell.js +10 -10
  210. package/dist/Table/TableHeaderCell.d.ts +8 -1
  211. package/dist/Table/TableHeaderCell.d.ts.map +1 -1
  212. package/dist/Table/TableHeaderCell.js +16 -16
  213. package/dist/Table/TableRow.d.ts +6 -1
  214. package/dist/Table/TableRow.d.ts.map +1 -1
  215. package/dist/Table/TableRow.js +15 -7
  216. package/dist/Table/index.d.ts +4 -1
  217. package/dist/Table/index.d.ts.map +1 -1
  218. package/dist/Table/index.js +3 -2
  219. package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
  220. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  221. package/dist/Table/plugins/pagination/paginateData.js +8 -3
  222. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  223. package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
  224. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  225. package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
  226. package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
  227. package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
  228. package/dist/Table/plugins/stickyColumns/index.js +3 -0
  229. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
  230. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
  231. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
  232. package/dist/Table/tableContextMenu.d.ts +33 -0
  233. package/dist/Table/tableContextMenu.d.ts.map +1 -0
  234. package/dist/Table/tableContextMenu.js +133 -0
  235. package/dist/Table/types.d.ts +161 -5
  236. package/dist/Table/types.d.ts.map +1 -1
  237. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  238. package/dist/Table/useBaseTablePlugins.js +1 -1
  239. package/dist/Text/text.stylex.d.ts +2 -2
  240. package/dist/Text/text.stylex.js +2 -2
  241. package/dist/TextArea/TextArea.d.ts +22 -1
  242. package/dist/TextArea/TextArea.d.ts.map +1 -1
  243. package/dist/TextArea/TextArea.js +41 -9
  244. package/dist/TextInput/TextInput.d.ts +23 -2
  245. package/dist/TextInput/TextInput.d.ts.map +1 -1
  246. package/dist/TextInput/TextInput.js +55 -10
  247. package/dist/TimeInput/TimeInput.d.ts +23 -1
  248. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  249. package/dist/TimeInput/TimeInput.js +53 -10
  250. package/dist/Timestamp/Timestamp.d.ts +1 -1
  251. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  252. package/dist/Timestamp/Timestamp.js +28 -3
  253. package/dist/Toast/Toast.d.ts.map +1 -1
  254. package/dist/Toast/Toast.js +14 -0
  255. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  256. package/dist/Toast/ToastViewport.js +132 -3
  257. package/dist/ToggleButton/ToggleButton.d.ts +7 -9
  258. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  259. package/dist/ToggleButton/ToggleButton.js +34 -57
  260. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  261. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  262. package/dist/Tokenizer/Tokenizer.js +27 -5
  263. package/dist/Toolbar/Toolbar.d.ts +3 -3
  264. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  265. package/dist/Toolbar/Toolbar.js +51 -7
  266. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  267. package/dist/Tooltip/useTooltip.js +57 -9
  268. package/dist/TreeList/TreeList.d.ts +1 -1
  269. package/dist/TreeList/TreeList.d.ts.map +1 -1
  270. package/dist/TreeList/TreeList.js +72 -2
  271. package/dist/TreeList/TreeListItem.d.ts +11 -1
  272. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  273. package/dist/TreeList/TreeListItem.js +51 -12
  274. package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
  275. package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
  276. package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
  277. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  278. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  279. package/dist/Typeahead/BaseTypeahead.js +67 -6
  280. package/dist/Typeahead/Typeahead.d.ts +24 -1
  281. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  282. package/dist/Typeahead/Typeahead.js +29 -5
  283. package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
  284. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
  285. package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
  286. package/dist/VisuallyHidden/index.d.ts +11 -0
  287. package/dist/VisuallyHidden/index.d.ts.map +1 -0
  288. package/dist/VisuallyHidden/index.js +13 -0
  289. package/dist/astryx.css +40 -1
  290. package/dist/astryx.umd.js +147 -0
  291. package/dist/astryx.umd.js.map +7 -0
  292. package/dist/hooks/focusableSelector.d.ts +22 -0
  293. package/dist/hooks/focusableSelector.d.ts.map +1 -0
  294. package/dist/hooks/focusableSelector.js +24 -0
  295. package/dist/hooks/index.d.ts +12 -2
  296. package/dist/hooks/index.d.ts.map +1 -1
  297. package/dist/hooks/index.js +7 -2
  298. package/dist/hooks/useAnnounce.d.ts +40 -0
  299. package/dist/hooks/useAnnounce.d.ts.map +1 -0
  300. package/dist/hooks/useAnnounce.js +142 -0
  301. package/dist/hooks/useClickableContainer.d.ts +16 -1
  302. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  303. package/dist/hooks/useClickableContainer.js +16 -4
  304. package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
  305. package/dist/hooks/useEntryAnimation.js +4 -4
  306. package/dist/hooks/useFocusTrap.d.ts +18 -0
  307. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  308. package/dist/hooks/useFocusTrap.js +87 -3
  309. package/dist/hooks/useGridFocus.d.ts +88 -1
  310. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  311. package/dist/hooks/useGridFocus.js +261 -62
  312. package/dist/hooks/useKeyboardHint.d.ts +82 -0
  313. package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
  314. package/dist/hooks/useKeyboardHint.js +220 -0
  315. package/dist/hooks/useListFocus.d.ts +78 -7
  316. package/dist/hooks/useListFocus.d.ts.map +1 -1
  317. package/dist/hooks/useListFocus.js +305 -52
  318. package/dist/hooks/useLongPress.d.ts +21 -0
  319. package/dist/hooks/useLongPress.d.ts.map +1 -0
  320. package/dist/hooks/useLongPress.js +89 -0
  321. package/dist/hooks/useTreeFocus.d.ts +157 -0
  322. package/dist/hooks/useTreeFocus.d.ts.map +1 -0
  323. package/dist/hooks/useTreeFocus.js +337 -0
  324. package/dist/hooks/useTypeahead.d.ts +63 -0
  325. package/dist/hooks/useTypeahead.d.ts.map +1 -0
  326. package/dist/hooks/useTypeahead.js +117 -0
  327. package/dist/index.d.ts +1 -0
  328. package/dist/index.d.ts.map +1 -1
  329. package/dist/index.js +1 -0
  330. package/dist/theme/generateThemeRules.js +1 -1
  331. package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
  332. package/dist/theme/syntax/SyntaxTheme.js +1 -1
  333. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  334. package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
  335. package/dist/theme/syntax/presets.d.ts +1 -1
  336. package/dist/theme/syntax/presets.d.ts.map +1 -1
  337. package/dist/theme/syntax/presets.js +1 -1
  338. package/dist/theme/syntax/tokens.d.ts +1 -1
  339. package/dist/theme/syntax/tokens.js +1 -1
  340. package/dist/theme/types.d.ts +1 -1
  341. package/dist/utils/dateTypes.d.ts +12 -0
  342. package/dist/utils/dateTypes.d.ts.map +1 -1
  343. package/dist/utils/dateTypes.js +41 -1
  344. package/dist/utils/index.d.ts +4 -0
  345. package/dist/utils/index.d.ts.map +1 -1
  346. package/dist/utils/index.js +3 -1
  347. package/dist/utils/inputAria.d.ts +29 -0
  348. package/dist/utils/inputAria.d.ts.map +1 -0
  349. package/dist/utils/inputAria.js +30 -0
  350. package/dist/utils/timeParser.d.ts.map +1 -1
  351. package/dist/utils/timeParser.js +5 -2
  352. package/package.json +15 -5
  353. package/src/Avatar/Avatar.test.tsx +37 -0
  354. package/src/Avatar/Avatar.tsx +10 -5
  355. package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
  356. package/src/Banner/Banner.doc.mjs +8 -0
  357. package/src/Banner/Banner.test.tsx +16 -7
  358. package/src/Banner/Banner.tsx +9 -2
  359. package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
  360. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
  361. package/src/Button/Button.doc.mjs +6 -0
  362. package/src/Button/Button.test.tsx +105 -11
  363. package/src/Button/Button.tsx +76 -21
  364. package/src/Calendar/Calendar.doc.mjs +4 -4
  365. package/src/Calendar/Calendar.test.tsx +168 -30
  366. package/src/Calendar/Calendar.tsx +121 -66
  367. package/src/Calendar/hooks/index.ts +0 -6
  368. package/src/Calendar/index.ts +1 -3
  369. package/src/Calendar/styles.ts +4 -9
  370. package/src/Carousel/Carousel.doc.mjs +7 -1
  371. package/src/Carousel/Carousel.test.tsx +20 -0
  372. package/src/Carousel/Carousel.tsx +16 -1
  373. package/src/Center/Center.doc.mjs +12 -2
  374. package/src/Center/Center.tsx +28 -3
  375. package/src/Chat/ChatComposer.doc.mjs +3 -0
  376. package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
  377. package/src/Chat/ChatMessageList.doc.mjs +8 -0
  378. package/src/Chat/ChatMessageList.test.tsx +18 -0
  379. package/src/Chat/ChatMessageList.tsx +16 -0
  380. package/src/Chat/useTriggerMenu.tsx +3 -0
  381. package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
  382. package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
  383. package/src/CheckboxInput/CheckboxInput.tsx +78 -6
  384. package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
  385. package/src/CheckboxList/CheckboxList.test.tsx +169 -16
  386. package/src/CheckboxList/CheckboxList.tsx +56 -3
  387. package/src/CheckboxList/CheckboxListContext.tsx +7 -0
  388. package/src/Citation/Citation.doc.mjs +10 -0
  389. package/src/Citation/Citation.test.tsx +117 -0
  390. package/src/Citation/Citation.tsx +9 -1
  391. package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
  392. package/src/CodeBlock/CodeBlock.test.tsx +115 -0
  393. package/src/CodeBlock/CodeBlock.tsx +61 -33
  394. package/src/CommandPalette/CommandPalette.test.tsx +47 -1
  395. package/src/CommandPalette/CommandPalette.tsx +9 -21
  396. package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
  397. package/src/ContextMenu/ContextMenu.test.tsx +155 -1
  398. package/src/ContextMenu/ContextMenu.tsx +113 -16
  399. package/src/DateInput/DateInput.doc.mjs +281 -56
  400. package/src/DateInput/DateInput.test.tsx +188 -2
  401. package/src/DateInput/DateInput.tsx +89 -10
  402. package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
  403. package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
  404. package/src/DateRangeInput/DateRangeInput.tsx +63 -5
  405. package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
  406. package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
  407. package/src/DateTimeInput/DateTimeInput.tsx +125 -17
  408. package/src/Dialog/Dialog.doc.mjs +2 -2
  409. package/src/Dialog/Dialog.tsx +12 -0
  410. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
  411. package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
  412. package/src/DropdownMenu/DropdownMenu.tsx +52 -18
  413. package/src/EmptyState/EmptyState.test.tsx +4 -2
  414. package/src/EmptyState/EmptyState.tsx +6 -2
  415. package/src/Field/Field.test.tsx +32 -0
  416. package/src/Field/Field.tsx +23 -5
  417. package/src/Field/FieldLabel.tsx +55 -17
  418. package/src/FileInput/FileInput.doc.mjs +17 -0
  419. package/src/FileInput/FileInput.test.tsx +283 -49
  420. package/src/FileInput/FileInput.tsx +76 -4
  421. package/src/Grid/Grid.doc.mjs +14 -4
  422. package/src/Grid/Grid.tsx +20 -0
  423. package/src/HoverCard/HoverCard.doc.mjs +3 -0
  424. package/src/HoverCard/HoverCard.test.tsx +189 -2
  425. package/src/HoverCard/HoverCard.tsx +20 -16
  426. package/src/HoverCard/useHoverCard.tsx +13 -10
  427. package/src/Icon/Icon.doc.mjs +8 -0
  428. package/src/InputGroup/InputGroup.doc.mjs +2 -2
  429. package/src/InputGroup/InputGroup.test.tsx +98 -60
  430. package/src/InputGroup/InputGroup.tsx +21 -4
  431. package/src/InputGroup/InputGroupContext.ts +9 -4
  432. package/src/InputGroup/index.ts +1 -0
  433. package/src/Kbd/Kbd.test.tsx +22 -4
  434. package/src/Kbd/Kbd.tsx +37 -12
  435. package/src/Layer/anchorName.test.ts +146 -0
  436. package/src/Layer/anchorName.ts +46 -0
  437. package/src/Layer/layerAnimations.stylex.ts +20 -4
  438. package/src/Layer/useLayer.doc.mjs +12 -2
  439. package/src/Layer/useLayer.tsx +100 -15
  440. package/src/Layout/Layout.doc.mjs +1 -1
  441. package/src/Layout/Layout.tsx +8 -16
  442. package/src/Layout/LayoutFooter.doc.mjs +4 -4
  443. package/src/Layout/LayoutFooter.tsx +3 -3
  444. package/src/Layout/LayoutHeader.doc.mjs +4 -4
  445. package/src/Layout/LayoutHeader.tsx +3 -3
  446. package/src/Layout/LayoutPanel.tsx +3 -3
  447. package/src/Layout/padding.stylex.ts +52 -0
  448. package/src/Lightbox/Lightbox.doc.mjs +9 -2
  449. package/src/Lightbox/Lightbox.test.tsx +53 -5
  450. package/src/Lightbox/Lightbox.tsx +9 -4
  451. package/src/Link/Link.doc.mjs +14 -0
  452. package/src/Link/Link.test.tsx +52 -2
  453. package/src/Link/Link.tsx +42 -7
  454. package/src/Link/LinkProvider.tsx +1 -0
  455. package/src/List/List.doc.mjs +7 -0
  456. package/src/Markdown/Markdown.doc.mjs +2 -0
  457. package/src/Markdown/Markdown.test.tsx +28 -26
  458. package/src/Markdown/Markdown.tsx +21 -6
  459. package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
  460. package/src/MobileNav/MobileNav.doc.mjs +8 -8
  461. package/src/MobileNav/MobileNav.tsx +13 -0
  462. package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
  463. package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
  464. package/src/MoreMenu/MoreMenu.tsx +0 -9
  465. package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
  466. package/src/MultiSelector/MultiSelector.test.tsx +375 -8
  467. package/src/MultiSelector/MultiSelector.tsx +145 -21
  468. package/src/MultiSelector/hooks.ts +27 -0
  469. package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
  470. package/src/NavMenu/NavHeadingMenu.tsx +50 -3
  471. package/src/NumberInput/NumberInput.doc.mjs +17 -0
  472. package/src/NumberInput/NumberInput.test.tsx +242 -40
  473. package/src/NumberInput/NumberInput.tsx +89 -11
  474. package/src/OverflowList/OverflowList.doc.mjs +17 -0
  475. package/src/Pagination/Pagination.doc.mjs +3 -3
  476. package/src/Pagination/Pagination.test.tsx +250 -14
  477. package/src/Pagination/Pagination.tsx +54 -29
  478. package/src/Popover/usePopover.doc.mjs +7 -3
  479. package/src/Popover/usePopover.tsx +49 -6
  480. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  481. package/src/PowerSearch/PowerSearch.test.tsx +97 -1
  482. package/src/PowerSearch/PowerSearch.tsx +16 -3
  483. package/src/ProgressBar/ProgressBar.test.tsx +45 -27
  484. package/src/ProgressBar/ProgressBar.tsx +3 -4
  485. package/src/RadioList/RadioList.doc.mjs +9 -0
  486. package/src/RadioList/RadioList.test.tsx +252 -16
  487. package/src/RadioList/RadioList.tsx +166 -10
  488. package/src/RadioList/RadioListItem.tsx +14 -2
  489. package/src/Resizable/Resizable.doc.mjs +1 -1
  490. package/src/Section/Section.doc.mjs +11 -0
  491. package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
  492. package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
  493. package/src/SegmentedControl/SegmentedControl.tsx +102 -54
  494. package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
  495. package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
  496. package/src/SelectableCard/SelectableCard.doc.mjs +15 -0
  497. package/src/Selector/Selector.doc.mjs +25 -0
  498. package/src/Selector/Selector.test.tsx +322 -15
  499. package/src/Selector/Selector.tsx +126 -40
  500. package/src/Selector/hooks.ts +23 -0
  501. package/src/SideNav/SideNav.test.tsx +16 -0
  502. package/src/SideNav/SideNavItem.tsx +2 -4
  503. package/src/Skeleton/Skeleton.doc.mjs +11 -1
  504. package/src/Skeleton/Skeleton.test.tsx +25 -0
  505. package/src/Skeleton/Skeleton.tsx +11 -1
  506. package/src/Slider/Slider.doc.mjs +19 -0
  507. package/src/Slider/Slider.test.tsx +158 -18
  508. package/src/Slider/Slider.tsx +54 -6
  509. package/src/Spinner/Spinner.tsx +7 -1
  510. package/src/Stack/Stack.doc.mjs +77 -0
  511. package/src/Stack/Stack.test.tsx +55 -5
  512. package/src/Stack/Stack.tsx +73 -24
  513. package/src/Stack/StackItem.test.tsx +23 -0
  514. package/src/Stack/StackItem.tsx +20 -23
  515. package/src/Switch/Switch.doc.mjs +15 -0
  516. package/src/Switch/Switch.test.tsx +162 -27
  517. package/src/Switch/Switch.tsx +61 -21
  518. package/src/TabList/Tab.tsx +6 -0
  519. package/src/TabList/TabList.doc.mjs +12 -0
  520. package/src/TabList/TabList.test.tsx +208 -0
  521. package/src/TabList/TabList.tsx +102 -12
  522. package/src/TabList/TabListContext.ts +7 -3
  523. package/src/TabList/TabMenu.tsx +6 -3
  524. package/src/Table/BaseTable.tsx +72 -41
  525. package/src/Table/Table.doc.mjs +14 -0
  526. package/src/Table/Table.test.tsx +39 -30
  527. package/src/Table/Table.tsx +27 -1
  528. package/src/Table/TableCell.tsx +25 -23
  529. package/src/Table/TableHeaderCell.tsx +28 -29
  530. package/src/Table/TableRow.tsx +37 -7
  531. package/src/Table/index.ts +6 -2
  532. package/src/Table/plugins/pagination/paginateData.ts +10 -3
  533. package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
  534. package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
  535. package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
  536. package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
  537. package/src/Table/plugins/stickyColumns/index.ts +4 -0
  538. package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
  539. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
  540. package/src/Table/tableContextMenu.test.tsx +157 -0
  541. package/src/Table/tableContextMenu.tsx +142 -0
  542. package/src/Table/types.ts +175 -4
  543. package/src/Table/useBaseTablePlugins.ts +1 -0
  544. package/src/Table/useTableColumnResize.doc.mjs +96 -0
  545. package/src/Table/useTableStickyColumns.doc.mjs +59 -0
  546. package/src/Text/Heading.doc.mjs +15 -2
  547. package/src/Text/Text.doc.mjs +7 -1
  548. package/src/Text/text.stylex.ts +2 -2
  549. package/src/TextArea/TextArea.doc.mjs +17 -0
  550. package/src/TextArea/TextArea.test.tsx +167 -35
  551. package/src/TextArea/TextArea.tsx +62 -15
  552. package/src/TextInput/TextInput.doc.mjs +17 -0
  553. package/src/TextInput/TextInput.test.tsx +168 -34
  554. package/src/TextInput/TextInput.tsx +77 -9
  555. package/src/TimeInput/TimeInput.doc.mjs +335 -60
  556. package/src/TimeInput/TimeInput.test.tsx +144 -7
  557. package/src/TimeInput/TimeInput.tsx +74 -5
  558. package/src/Timestamp/Timestamp.doc.mjs +9 -0
  559. package/src/Timestamp/Timestamp.test.tsx +44 -18
  560. package/src/Timestamp/Timestamp.tsx +30 -10
  561. package/src/Toast/Toast.tsx +14 -0
  562. package/src/Toast/ToastViewport.test.tsx +204 -0
  563. package/src/Toast/ToastViewport.tsx +167 -21
  564. package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
  565. package/src/ToggleButton/ToggleButton.test.tsx +39 -18
  566. package/src/ToggleButton/ToggleButton.tsx +46 -83
  567. package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
  568. package/src/Tokenizer/Tokenizer.test.tsx +105 -1
  569. package/src/Tokenizer/Tokenizer.tsx +41 -2
  570. package/src/Toolbar/Toolbar.doc.mjs +65 -5
  571. package/src/Toolbar/Toolbar.test.tsx +109 -6
  572. package/src/Toolbar/Toolbar.tsx +59 -5
  573. package/src/Tooltip/Tooltip.test.tsx +81 -0
  574. package/src/Tooltip/useTooltip.tsx +57 -11
  575. package/src/TreeList/TreeList.test.tsx +295 -6
  576. package/src/TreeList/TreeList.tsx +73 -1
  577. package/src/TreeList/TreeListItem.tsx +51 -5
  578. package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
  579. package/src/Typeahead/BaseTypeahead.tsx +86 -9
  580. package/src/Typeahead/Typeahead.doc.mjs +136 -30
  581. package/src/Typeahead/Typeahead.test.tsx +331 -1
  582. package/src/Typeahead/Typeahead.tsx +52 -1
  583. package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
  584. package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
  585. package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
  586. package/src/VisuallyHidden/index.ts +15 -0
  587. package/src/hooks/focusableSelector.ts +25 -0
  588. package/src/hooks/index.ts +28 -2
  589. package/src/hooks/useAnnounce.test.tsx +101 -0
  590. package/src/hooks/useAnnounce.ts +168 -0
  591. package/src/hooks/useClickableContainer.ts +16 -4
  592. package/src/hooks/useEntryAnimation.ts +16 -4
  593. package/src/hooks/useFocusTrap.test.tsx +132 -0
  594. package/src/hooks/useFocusTrap.ts +98 -4
  595. package/src/hooks/useGridFocus.doc.mjs +40 -2
  596. package/src/hooks/useGridFocus.test.tsx +132 -0
  597. package/src/hooks/useGridFocus.ts +343 -67
  598. package/src/hooks/useImageMode.test.ts +133 -0
  599. package/src/hooks/useKeyboardHint.doc.mjs +101 -0
  600. package/src/hooks/useKeyboardHint.test.tsx +70 -0
  601. package/src/hooks/useKeyboardHint.tsx +332 -0
  602. package/src/hooks/useListFocus.doc.mjs +50 -10
  603. package/src/hooks/useListFocus.test.tsx +375 -0
  604. package/src/hooks/useListFocus.ts +395 -57
  605. package/src/hooks/useLongPress.test.tsx +134 -0
  606. package/src/hooks/useLongPress.ts +119 -0
  607. package/src/hooks/useTreeFocus.doc.mjs +140 -0
  608. package/src/hooks/useTreeFocus.test.tsx +214 -0
  609. package/src/hooks/useTreeFocus.ts +559 -0
  610. package/src/hooks/useTypeahead.test.tsx +109 -0
  611. package/src/hooks/useTypeahead.ts +183 -0
  612. package/src/index.ts +1 -0
  613. package/src/theme/derivedVarRegistry.test.ts +4 -0
  614. package/src/theme/generateThemeRules.test.ts +7 -8
  615. package/src/theme/generateThemeRules.ts +1 -1
  616. package/src/theme/syntax/SyntaxTheme.tsx +1 -1
  617. package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
  618. package/src/theme/syntax/presets.ts +5 -2
  619. package/src/theme/syntax/tokens.ts +1 -1
  620. package/src/theme/types.ts +1 -1
  621. package/src/utils/dateTypes.test.ts +40 -0
  622. package/src/utils/dateTypes.ts +40 -0
  623. package/src/utils/index.ts +9 -0
  624. package/src/utils/inputAria.test.ts +39 -0
  625. package/src/utils/inputAria.ts +58 -0
  626. package/src/utils/timeParser.test.ts +10 -0
  627. package/src/utils/timeParser.ts +5 -2
  628. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
  629. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
  630. package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
  631. package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file CheckboxInput.tsx
7
- * @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus
7
+ * @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus, useTooltip
8
8
  * @output Exports CheckboxInput component, CheckboxInputProps
9
9
  * @position Core implementation; consumed by index.ts, tested by CheckboxInput.test.tsx
10
10
  *
@@ -19,6 +19,7 @@
19
19
  import {
20
20
  useId,
21
21
  useCallback,
22
+ use,
22
23
  useOptimistic,
23
24
  useTransition,
24
25
  type ChangeEvent,
@@ -44,9 +45,11 @@ import {FieldStatus} from '../FieldStatus/FieldStatus';
44
45
  import type {IconType} from '../Icon';
45
46
  import type {InputStatus} from '../Field/types';
46
47
  import {Spinner} from '../Spinner';
48
+ import {useTooltip} from '../Tooltip';
47
49
  import {mergeProps, mergeRefs} from '../utils';
48
50
  import {checkboxScope} from './checkbox.markers.stylex';
49
51
  import {themeProps} from '../utils/themeProps';
52
+ import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
50
53
 
51
54
  const styles = stylex.create({
52
55
  container: {
@@ -269,6 +272,27 @@ export interface CheckboxInputProps extends Omit<BaseProps, 'onChange'> {
269
272
  * @default false
270
273
  */
271
274
  isDisabled?: boolean;
275
+ /**
276
+ * Explains why the checkbox is disabled. When set together with
277
+ * `isDisabled`, the checkbox shows a tooltip with this text on hover and
278
+ * keyboard focus, and the control stays focusable (via `aria-disabled`) so
279
+ * the reason is discoverable by keyboard and assistive technology.
280
+ * Activation stays blocked.
281
+ *
282
+ * Use this instead of wrapping a disabled checkbox in `Tooltip` — disabled
283
+ * controls don't emit the pointer events an external tooltip needs.
284
+ *
285
+ * @example
286
+ * ```
287
+ * <CheckboxInput
288
+ * label="Accept terms"
289
+ * value={accepted}
290
+ * isDisabled
291
+ * disabledMessage="Terms are managed by your administrator"
292
+ * />
293
+ * ```
294
+ */
295
+ disabledMessage?: string;
272
296
  /**
273
297
  * Whether the checkbox is read-only.
274
298
  * Displays the current state at full opacity but prevents interaction.
@@ -350,6 +374,7 @@ export function CheckboxInput({
350
374
  isLoading = false,
351
375
  value,
352
376
  isDisabled = false,
377
+ disabledMessage,
353
378
  isReadOnly = false,
354
379
  isOptional = false,
355
380
  isRequired = false,
@@ -372,11 +397,37 @@ export function CheckboxInput({
372
397
  const [optimisticValue, setOptimisticValue] = useOptimistic(value);
373
398
  const isBusy = isLoading || optimisticValue !== value;
374
399
 
400
+ // Disabled-reason tooltip. Disabled controls swallow pointer events, so the
401
+ // tooltip listeners attach to the checkbox row (which already exists) and the
402
+ // native checkbox stays perceivable via aria-disabled instead of the disabled
403
+ // attribute. Value mutation is blocked by the isDisabled guard in onChange.
404
+ const showsDisabledMessage = isDisabled && !!disabledMessage;
405
+ // Keep the native checkbox focusable via aria-disabled either when it renders
406
+ // its own reason tooltip, or when it sits in a CheckboxList whose whole-group
407
+ // `disabledMessage` (shown on the group container) needs each checkbox to
408
+ // stay keyboard-perceivable. The group signals this through context rather
409
+ // than a public prop.
410
+ const checkboxListContext = use(CheckboxListContext);
411
+ const isFocusableDisabled =
412
+ isDisabled &&
413
+ (showsDisabledMessage ||
414
+ (checkboxListContext?.hasDisabledMessage ?? false));
415
+ const disabledMessageTooltip = useTooltip({
416
+ placement: 'above',
417
+ // The container row is not naturally focusable; focusin bubbles up from the
418
+ // native checkbox, so always attach focus listeners.
419
+ focusTrigger: 'always',
420
+ isEnabled: showsDisabledMessage,
421
+ });
422
+
375
423
  const isIndeterminate = optimisticValue === 'indeterminate';
376
424
  const isChecked = optimisticValue === true;
377
425
  const isCheckedOrIndeterminate = isChecked || isIndeterminate;
378
426
 
379
- // Sync the native indeterminate DOM property (can't be set via JSX attribute)
427
+ // Sync the native indeterminate DOM property (can't be set via JSX
428
+ // attribute). On a native checkbox this is the authoritative way to expose
429
+ // the mixed state — a separate aria-checked="mixed" would be redundant and
430
+ // can desync from / override the native state (forms-16), so it is omitted.
380
431
  const indeterminateRef = useCallback(
381
432
  (el: HTMLInputElement | null) => {
382
433
  if (el) {
@@ -395,6 +446,9 @@ export function CheckboxInput({
395
446
  if (status?.message) {
396
447
  describedByParts.push(statusMessageID);
397
448
  }
449
+ if (showsDisabledMessage) {
450
+ describedByParts.push(disabledMessageTooltip.describedBy);
451
+ }
398
452
  const ariaDescribedBy =
399
453
  describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
400
454
 
@@ -407,6 +461,15 @@ export function CheckboxInput({
407
461
  style,
408
462
  )}>
409
463
  <div
464
+ ref={el => {
465
+ // Interaction (hover/focus) listeners for the disabled-message
466
+ // tooltip attach to the whole row for a larger trigger target;
467
+ // positioning anchors on the checkbox itself (below) so the tooltip
468
+ // appears next to the control, not the far edge of the row.
469
+ // Handlers are gated internally by isEnabled, so attaching
470
+ // unconditionally is safe.
471
+ disabledMessageTooltip.interactionRef(el);
472
+ }}
410
473
  {...stylex.props(
411
474
  styles.container,
412
475
  isLabelHidden && styles.containerLabelHidden,
@@ -414,15 +477,23 @@ export function CheckboxInput({
414
477
  )}>
415
478
  <div {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}>
416
479
  <input
417
- ref={mergeRefs(ref, indeterminateRef)}
480
+ ref={mergeRefs(
481
+ ref,
482
+ indeterminateRef,
483
+ disabledMessageTooltip.positionRef,
484
+ )}
418
485
  id={id}
419
486
  type="checkbox"
420
487
  checked={isChecked}
421
- disabled={isDisabled}
488
+ // With a disabledMessage the checkbox keeps focusability via
489
+ // aria-disabled so the reason is focus-discoverable; toggling is
490
+ // still blocked by the isDisabled guard in onChange below.
491
+ disabled={isDisabled && !isFocusableDisabled}
492
+ aria-disabled={isFocusableDisabled ? 'true' : undefined}
422
493
  readOnly={isReadOnly}
423
494
  required={isRequired}
424
495
  onChange={e => {
425
- if (isBusy || isReadOnly) {
496
+ if (isDisabled || isBusy || isReadOnly) {
426
497
  return;
427
498
  }
428
499
  const checked = e.target.checked;
@@ -436,7 +507,6 @@ export function CheckboxInput({
436
507
  }}
437
508
  onFocus={onFocus}
438
509
  onBlur={onBlur}
439
- aria-checked={isIndeterminate ? 'mixed' : undefined}
440
510
  aria-readonly={isReadOnly || undefined}
441
511
  aria-describedby={ariaDescribedBy}
442
512
  aria-invalid={status?.type === 'error' ? true : undefined}
@@ -525,6 +595,8 @@ export function CheckboxInput({
525
595
  variant="detached"
526
596
  />
527
597
  )}
598
+ {showsDisabledMessage &&
599
+ disabledMessageTooltip.renderTooltip(disabledMessage)}
528
600
  </div>
529
601
  );
530
602
  }
@@ -77,6 +77,12 @@ export const docs = {
77
77
  description: 'Whether all checkbox items are disabled.',
78
78
  default: 'false',
79
79
  },
80
+ {
81
+ name: 'disabledMessage',
82
+ type: 'string',
83
+ description:
84
+ 'Explains why the group is disabled. Applies to the whole-group disabled state (isDisabled), not per item. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the checkboxes focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled CheckboxList in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
85
+ },
80
86
  {
81
87
  name: 'status',
82
88
  type: 'InputStatus',
@@ -99,6 +105,7 @@ export const docs = {
99
105
  { guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
100
106
  { guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
101
107
  { guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
108
+ { guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
102
109
  ],
103
110
  },
104
111
  };
@@ -113,6 +120,7 @@ export const docsZh = {
113
120
  { guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
114
121
  { guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
115
122
  { guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
123
+ { guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
116
124
  ],
117
125
  },
118
126
  };
@@ -129,6 +137,7 @@ export const docsDense = {
129
137
  { guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
130
138
  { guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
131
139
  { guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
140
+ { guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
132
141
  ],
133
142
  },
134
143
  };
@@ -9,13 +9,46 @@
9
9
  * SYNC: When CheckboxList.tsx or CheckboxListItem.tsx changes, update tests to match new behavior
10
10
  */
11
11
 
12
- import {describe, it, expect, vi} from 'vitest';
13
- import {render, screen, fireEvent, within} from '@testing-library/react';
12
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
13
+ import {
14
+ render,
15
+ screen,
16
+ fireEvent,
17
+ within,
18
+ waitFor,
19
+ } from '@testing-library/react';
14
20
  import userEvent from '@testing-library/user-event';
15
21
  import {CheckboxList} from './CheckboxList';
16
22
  import {CheckboxListItem} from './CheckboxListItem';
17
23
  import {List} from '../List/List';
18
24
 
25
+ // Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
26
+ // reflects its open state via a `popover-open` attribute the tests can assert.
27
+ beforeEach(() => {
28
+ HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
29
+ this.setAttribute('popover-open', '');
30
+ const event = new Event('toggle', {bubbles: false});
31
+ Object.defineProperty(event, 'newState', {value: 'open'});
32
+ this.dispatchEvent(event);
33
+ });
34
+ HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
35
+ this.removeAttribute('popover-open');
36
+ const event = new Event('toggle', {bubbles: false});
37
+ Object.defineProperty(event, 'newState', {value: 'closed'});
38
+ this.dispatchEvent(event);
39
+ });
40
+ const originalMatches = HTMLElement.prototype.matches;
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ (HTMLElement.prototype as any).matches = function (
43
+ selector: string,
44
+ ): boolean {
45
+ if (selector === ':popover-open') {
46
+ return this.hasAttribute('popover-open');
47
+ }
48
+ return originalMatches.call(this, selector);
49
+ };
50
+ });
51
+
19
52
  describe('CheckboxList', () => {
20
53
  it('renders with label', () => {
21
54
  render(
@@ -26,6 +59,25 @@ describe('CheckboxList', () => {
26
59
  expect(screen.getByText('Preferences')).toBeInTheDocument();
27
60
  });
28
61
 
62
+ it('wraps items in a group named by the label (forms audit: group role)', () => {
63
+ render(
64
+ <CheckboxList label="Preferences" value={[]} onChange={() => {}}>
65
+ <CheckboxListItem label="Option A" value="a" />
66
+ </CheckboxList>,
67
+ );
68
+ // The checkboxes are wrapped in a role="group" whose accessible name comes
69
+ // from the field label (via aria-labelledby). The label is rendered as a
70
+ // <span> (not a literal <label>, which can't name a group) with no
71
+ // orphaned htmlFor.
72
+ const group = screen.getByRole('group', {name: 'Preferences'});
73
+ expect(group).toBeInTheDocument();
74
+ const label = screen.getByText('Preferences');
75
+ expect(label.tagName).toBe('SPAN');
76
+ expect(label.closest('label')).toBeNull();
77
+ expect(label).not.toHaveAttribute('for');
78
+ expect(group.getAttribute('aria-labelledby')).toBe(label.id);
79
+ });
80
+
29
81
  it('renders checkbox items', () => {
30
82
  render(
31
83
  <CheckboxList label="Preferences" value={[]} onChange={() => {}}>
@@ -39,10 +91,7 @@ describe('CheckboxList', () => {
39
91
 
40
92
  it('checks the correct items based on value prop', () => {
41
93
  render(
42
- <CheckboxList
43
- label="Preferences"
44
- value={['a', 'c']}
45
- onChange={() => {}}>
94
+ <CheckboxList label="Preferences" value={['a', 'c']} onChange={() => {}}>
46
95
  <CheckboxListItem label="Option A" value="a" />
47
96
  <CheckboxListItem label="Option B" value="b" />
48
97
  <CheckboxListItem label="Option C" value="c" />
@@ -58,10 +107,7 @@ describe('CheckboxList', () => {
58
107
  const user = userEvent.setup();
59
108
  const handleChange = vi.fn();
60
109
  render(
61
- <CheckboxList
62
- label="Preferences"
63
- value={['a']}
64
- onChange={handleChange}>
110
+ <CheckboxList label="Preferences" value={['a']} onChange={handleChange}>
65
111
  <CheckboxListItem label="Option A" value="a" />
66
112
  <CheckboxListItem label="Option B" value="b" />
67
113
  </CheckboxList>,
@@ -272,11 +318,7 @@ describe('CheckboxList', () => {
272
318
  isChecked={false}
273
319
  onCheck={handleSelectAll}
274
320
  />
275
- <CheckboxListItem
276
- label="Name"
277
- isChecked={true}
278
- onCheck={handleCheck}
279
- />
321
+ <CheckboxListItem label="Name" isChecked={true} onCheck={handleCheck} />
280
322
  <CheckboxListItem
281
323
  label="Email"
282
324
  isChecked={false}
@@ -347,8 +389,15 @@ describe('CheckboxListItem standalone mode', () => {
347
389
  <CheckboxListItem label="Partial" isChecked="indeterminate" />
348
390
  </List>,
349
391
  );
392
+ // The inner native checkbox exposes mixed state via the indeterminate DOM
393
+ // property (not a redundant aria-checked, forms-16); the list row still
394
+ // carries aria-checked="mixed" for its own listitem semantics.
350
395
  const checkbox = screen.getByRole('checkbox');
351
- expect(checkbox).toHaveAttribute('aria-checked', 'mixed');
396
+ expect(checkbox).toBeInstanceOf(HTMLInputElement);
397
+ if (checkbox instanceof HTMLInputElement) {
398
+ expect(checkbox.indeterminate).toBe(true);
399
+ }
400
+ expect(checkbox).not.toHaveAttribute('aria-checked');
352
401
  });
353
402
 
354
403
  it('calls onCheck with true when clicking indeterminate item', async () => {
@@ -500,4 +549,108 @@ describe('CheckboxListItem ARIA props', () => {
500
549
  expect(item).toHaveAttribute('aria-describedby', 'help-text');
501
550
  expect(item).toHaveAttribute('aria-label', 'custom label');
502
551
  });
552
+
553
+ describe('disabledMessage', () => {
554
+ const h = {hidden: true} as const;
555
+
556
+ function renderGroup(props?: {onChange?: (v: string[]) => void}) {
557
+ return render(
558
+ <CheckboxList
559
+ label="Notifications"
560
+ value={['email']}
561
+ onChange={props?.onChange ?? (() => {})}
562
+ isDisabled
563
+ disabledMessage="Notifications are managed by your administrator">
564
+ <CheckboxListItem label="Email" value="email" />
565
+ <CheckboxListItem label="SMS" value="sms" />
566
+ </CheckboxList>,
567
+ );
568
+ }
569
+
570
+ it('shows the reason tooltip on hover when the group is disabled with a reason', async () => {
571
+ renderGroup();
572
+ const tooltip = screen.getByRole('tooltip', h);
573
+ expect(tooltip).toHaveTextContent(
574
+ 'Notifications are managed by your administrator',
575
+ );
576
+ const group = screen.getByRole('group');
577
+ fireEvent.mouseEnter(group);
578
+ await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
579
+ fireEvent.mouseLeave(group);
580
+ await waitFor(() => expect(tooltip).not.toHaveAttribute('popover-open'));
581
+ });
582
+
583
+ it('shows the reason tooltip on keyboard focus', async () => {
584
+ const user = userEvent.setup();
585
+ renderGroup();
586
+ const tooltip = screen.getByRole('tooltip', h);
587
+ await user.tab();
588
+ await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
589
+ });
590
+
591
+ it('does not render a tooltip when not disabled', () => {
592
+ render(
593
+ <CheckboxList
594
+ label="Notifications"
595
+ value={['email']}
596
+ onChange={() => {}}
597
+ disabledMessage="Notifications are managed by your administrator">
598
+ <CheckboxListItem label="Email" value="email" />
599
+ </CheckboxList>,
600
+ );
601
+ expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
602
+ });
603
+
604
+ it('does not render a tooltip when disabled without a reason', () => {
605
+ render(
606
+ <CheckboxList
607
+ label="Notifications"
608
+ value={['email']}
609
+ onChange={() => {}}
610
+ isDisabled>
611
+ <CheckboxListItem label="Email" value="email" />
612
+ </CheckboxList>,
613
+ );
614
+ expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
615
+ });
616
+
617
+ it('keeps checkboxes focusable via aria-disabled when a reason is provided', () => {
618
+ renderGroup();
619
+ for (const checkbox of screen.getAllByRole('checkbox', h)) {
620
+ expect(checkbox).not.toBeDisabled();
621
+ expect(checkbox).toHaveAttribute('aria-disabled', 'true');
622
+ }
623
+ });
624
+
625
+ it('links the reason tooltip from the group via aria-describedby', () => {
626
+ renderGroup();
627
+ const group = screen.getByRole('group');
628
+ const tooltip = screen.getByRole('tooltip', h);
629
+ expect(group.getAttribute('aria-describedby')).toContain(tooltip.id);
630
+ });
631
+
632
+ it('blocks toggling while focusable-disabled', () => {
633
+ const onChange = vi.fn();
634
+ renderGroup({onChange});
635
+ const sms = screen.getByRole('checkbox', {name: 'SMS', hidden: true});
636
+ fireEvent.click(sms);
637
+ expect(onChange).not.toHaveBeenCalled();
638
+ });
639
+
640
+ it('keeps checkboxes natively disabled when disabled without a reason', () => {
641
+ render(
642
+ <CheckboxList
643
+ label="Notifications"
644
+ value={['email']}
645
+ onChange={() => {}}
646
+ isDisabled>
647
+ <CheckboxListItem label="Email" value="email" />
648
+ <CheckboxListItem label="SMS" value="sms" />
649
+ </CheckboxList>,
650
+ );
651
+ for (const checkbox of screen.getAllByRole('checkbox', h)) {
652
+ expect(checkbox).toBeDisabled();
653
+ }
654
+ });
655
+ });
503
656
  });
@@ -30,6 +30,7 @@ import {Field} from '../Field/Field';
30
30
  import type {InputStatus} from '../Field/types';
31
31
  import {List} from '../List/List';
32
32
  import type {ListDensity} from '../List/ListContext';
33
+ import {useTooltip} from '../Tooltip';
33
34
  import {mergeProps} from '../utils';
34
35
  import {themeProps} from '../utils/themeProps';
35
36
  import {
@@ -93,6 +94,18 @@ export interface CheckboxListProps extends Omit<
93
94
  * @default false
94
95
  */
95
96
  isDisabled?: boolean;
97
+ /**
98
+ * Explains why the checkbox group is disabled. Applies to the whole-group
99
+ * disabled state (`isDisabled`), not individual items. When set together with
100
+ * `isDisabled`, the group shows a tooltip with this text on hover and keyboard
101
+ * focus, and its checkboxes stay focusable (via `aria-disabled`) so the reason
102
+ * is discoverable by keyboard and assistive technology. Toggling stays
103
+ * blocked.
104
+ *
105
+ * Use this instead of wrapping a disabled group in `Tooltip` — disabled
106
+ * controls don't emit the pointer events an external tooltip needs.
107
+ */
108
+ disabledMessage?: string;
96
109
  /**
97
110
  * Whether all checkbox items are read-only.
98
111
  * Displays the current state at full opacity but prevents interaction.
@@ -141,6 +154,7 @@ export function CheckboxList({
141
154
  density = 'balanced',
142
155
  hasDividers = false,
143
156
  isDisabled = false,
157
+ disabledMessage,
144
158
  isReadOnly = false,
145
159
  children,
146
160
  ref,
@@ -151,6 +165,7 @@ export function CheckboxList({
151
165
  'data-testid': dataTestId,
152
166
  }: CheckboxListProps) {
153
167
  const inputID = useId();
168
+ const labelID = useId();
154
169
  const descriptionID = useId();
155
170
  const statusMessageID = useId();
156
171
 
@@ -162,6 +177,19 @@ export function CheckboxList({
162
177
  // the transition settles, so the spinner clears without manual cleanup.
163
178
  const [loadingValue, setLoadingValue] = useOptimistic<string | null>(null);
164
179
 
180
+ // Disabled-reason tooltip. Applies to the whole-group disabled state. Disabled
181
+ // controls swallow pointer events, so the tooltip listeners attach to the
182
+ // group container and the checkboxes stay perceivable via aria-disabled
183
+ // instead of the disabled attribute. Toggling is blocked in the item.
184
+ const showsDisabledMessage = isDisabled && !!disabledMessage;
185
+ const disabledMessageTooltip = useTooltip({
186
+ placement: 'above',
187
+ // The group container is not naturally focusable; focusin bubbles up from
188
+ // the checkboxes, so always attach focus listeners.
189
+ focusTrigger: 'always',
190
+ isEnabled: showsDisabledMessage,
191
+ });
192
+
165
193
  const handleChange = useCallback(
166
194
  (newValues: string[], toggledValue?: string) => {
167
195
  onChange?.(newValues);
@@ -189,6 +217,7 @@ export function CheckboxList({
189
217
  value: isCollectionMode ? optimisticValue : undefined,
190
218
  onChange: isCollectionMode ? handleChange : undefined,
191
219
  isDisabled,
220
+ hasDisabledMessage: showsDisabledMessage,
192
221
  isReadOnly,
193
222
  loadingValue,
194
223
  }),
@@ -197,6 +226,7 @@ export function CheckboxList({
197
226
  optimisticValue,
198
227
  handleChange,
199
228
  isDisabled,
229
+ showsDisabledMessage,
200
230
  isReadOnly,
201
231
  loadingValue,
202
232
  ],
@@ -210,6 +240,8 @@ export function CheckboxList({
210
240
  isLabelHidden={isLabelHidden}
211
241
  description={description}
212
242
  inputID={inputID}
243
+ labelID={labelID}
244
+ isGroupLabel
213
245
  descriptionID={description ? descriptionID : undefined}
214
246
  isDisabled={isDisabled}
215
247
  status={
@@ -226,10 +258,31 @@ export function CheckboxList({
226
258
  xstyle={xstyle}
227
259
  {...mergeProps(themeProps('checkbox-list'), {className, style})}>
228
260
  <CheckboxListContext value={contextValue}>
229
- <List density={density} hasDividers={hasDividers}>
230
- {children}
231
- </List>
261
+ <div
262
+ ref={el => {
263
+ // Anchor + hover/focus listeners for the disabled-message tooltip.
264
+ // Handlers are gated internally by isEnabled, so attaching
265
+ // unconditionally is safe.
266
+ disabledMessageTooltip.ref(el);
267
+ }}
268
+ role="group"
269
+ aria-labelledby={labelID}
270
+ aria-describedby={
271
+ [
272
+ description ? descriptionID : null,
273
+ status?.message ? statusMessageID : null,
274
+ showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
275
+ ]
276
+ .filter(Boolean)
277
+ .join(' ') || undefined
278
+ }>
279
+ <List density={density} hasDividers={hasDividers}>
280
+ {children}
281
+ </List>
282
+ </div>
232
283
  </CheckboxListContext>
284
+ {showsDisabledMessage &&
285
+ disabledMessageTooltip.renderTooltip(disabledMessage)}
233
286
  </Field>
234
287
  );
235
288
  }
@@ -21,6 +21,13 @@ export interface CheckboxListContextValue {
21
21
  */
22
22
  onChange?: (values: string[], toggledValue?: string) => void;
23
23
  isDisabled: boolean;
24
+ /**
25
+ * True when the whole group is disabled *and* a `disabledMessage` is set. In
26
+ * that mode items stay focusable via `aria-disabled` (instead of the native
27
+ * `disabled` attribute) so the group's disabled-reason tooltip is keyboard-
28
+ * and AT-discoverable; toggling is still blocked.
29
+ */
30
+ hasDisabledMessage?: boolean;
24
31
  isReadOnly: boolean;
25
32
  /**
26
33
  * The value of the item with a pending `changeAction`, or null when idle.
@@ -56,6 +56,16 @@ export const docs = {
56
56
  ],
57
57
  },
58
58
 
59
+ // `source` is a custom object type the docsite preview cannot generate
60
+ // automatically; without these defaults the properties tab shows the
61
+ // missing-required-props placeholder instead of an interactive preview.
62
+ playground: {
63
+ defaults: {
64
+ source: {title: 'Astryx Design', url: 'https://example.com'},
65
+ number: 1,
66
+ },
67
+ },
68
+
59
69
  props: [
60
70
  {
61
71
  name: 'source',