@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d

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 (567) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +12 -12
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +11 -5
  5. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
  6. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  7. package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
  8. package/dist/Button/Button.d.ts.map +1 -1
  9. package/dist/Button/Button.js +2 -4
  10. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  11. package/dist/ButtonGroup/ButtonGroup.js +0 -1
  12. package/dist/Calendar/Calendar.d.ts +5 -4
  13. package/dist/Calendar/Calendar.d.ts.map +1 -1
  14. package/dist/Calendar/Calendar.js +82 -43
  15. package/dist/Calendar/hooks/index.d.ts +0 -2
  16. package/dist/Calendar/hooks/index.d.ts.map +1 -1
  17. package/dist/Calendar/hooks/index.js +1 -2
  18. package/dist/Calendar/index.d.ts +3 -3
  19. package/dist/Calendar/index.d.ts.map +1 -1
  20. package/dist/Calendar/index.js +1 -1
  21. package/dist/Calendar/styles.d.ts +3 -9
  22. package/dist/Calendar/styles.d.ts.map +1 -1
  23. package/dist/Calendar/styles.js +3 -11
  24. package/dist/Carousel/Carousel.d.ts.map +1 -1
  25. package/dist/Carousel/Carousel.js +17 -3
  26. package/dist/Center/Center.d.ts +11 -1
  27. package/dist/Center/Center.d.ts.map +1 -1
  28. package/dist/Center/Center.js +9 -3
  29. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  30. package/dist/Chat/ChatComposerInput.js +0 -1
  31. package/dist/Chat/ChatMessageList.d.ts +14 -1
  32. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  33. package/dist/Chat/ChatMessageList.js +2 -0
  34. package/dist/Chat/useTriggerMenu.d.ts +8 -1
  35. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  36. package/dist/Chat/useTriggerMenu.js +15 -3
  37. package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
  38. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  39. package/dist/CheckboxInput/CheckboxInput.js +51 -9
  40. package/dist/CheckboxList/CheckboxList.d.ts +13 -1
  41. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  42. package/dist/CheckboxList/CheckboxList.js +39 -9
  43. package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
  44. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  45. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  46. package/dist/CheckboxList/CheckboxListItem.js +0 -1
  47. package/dist/Citation/Citation.d.ts.map +1 -1
  48. package/dist/Citation/Citation.js +9 -5
  49. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  50. package/dist/CodeBlock/CodeBlock.js +51 -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 +167 -99
  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/Field/Field.d.ts +19 -2
  71. package/dist/Field/Field.d.ts.map +1 -1
  72. package/dist/Field/Field.js +4 -0
  73. package/dist/Field/FieldLabel.d.ts +21 -2
  74. package/dist/Field/FieldLabel.d.ts.map +1 -1
  75. package/dist/Field/FieldLabel.js +41 -26
  76. package/dist/FileInput/FileInput.d.ts +22 -1
  77. package/dist/FileInput/FileInput.d.ts.map +1 -1
  78. package/dist/FileInput/FileInput.js +56 -10
  79. package/dist/Grid/Grid.d.ts +11 -1
  80. package/dist/Grid/Grid.d.ts.map +1 -1
  81. package/dist/Grid/Grid.js +32 -6
  82. package/dist/InputGroup/InputGroup.d.ts +4 -3
  83. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  84. package/dist/InputGroup/InputGroup.js +16 -6
  85. package/dist/InputGroup/InputGroupContext.d.ts +4 -0
  86. package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
  87. package/dist/InputGroup/InputGroupContext.js +2 -2
  88. package/dist/InputGroup/groupStyles.d.ts +1 -1
  89. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  90. package/dist/InputGroup/groupStyles.js +3 -3
  91. package/dist/InputGroup/index.d.ts +1 -0
  92. package/dist/InputGroup/index.d.ts.map +1 -1
  93. package/dist/Kbd/Kbd.d.ts.map +1 -1
  94. package/dist/Kbd/Kbd.js +33 -1
  95. package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
  96. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  97. package/dist/Layer/layerAnimations.stylex.js +8 -4
  98. package/dist/Layer/useLayer.d.ts +10 -0
  99. package/dist/Layer/useLayer.d.ts.map +1 -1
  100. package/dist/Layer/useLayer.js +64 -9
  101. package/dist/Layout/Layout.d.ts +4 -11
  102. package/dist/Layout/Layout.d.ts.map +1 -1
  103. package/dist/Layout/Layout.js +10 -11
  104. package/dist/Layout/LayoutFooter.d.ts +2 -2
  105. package/dist/Layout/LayoutFooter.d.ts.map +1 -1
  106. package/dist/Layout/LayoutHeader.d.ts +2 -2
  107. package/dist/Layout/LayoutHeader.d.ts.map +1 -1
  108. package/dist/Layout/LayoutPanel.d.ts +2 -2
  109. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  110. package/dist/Layout/padding.stylex.d.ts +51 -0
  111. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  112. package/dist/Layout/padding.stylex.js +63 -0
  113. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  114. package/dist/Lightbox/Lightbox.js +4 -2
  115. package/dist/Link/Link.d.ts +16 -1
  116. package/dist/Link/Link.d.ts.map +1 -1
  117. package/dist/Link/Link.js +18 -7
  118. package/dist/Markdown/Markdown.d.ts.map +1 -1
  119. package/dist/Markdown/Markdown.js +7 -0
  120. package/dist/MoreMenu/MoreMenu.d.ts +1 -7
  121. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  122. package/dist/MoreMenu/MoreMenu.js +0 -2
  123. package/dist/MultiSelector/MultiSelector.d.ts +27 -2
  124. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  125. package/dist/MultiSelector/MultiSelector.js +141 -42
  126. package/dist/MultiSelector/hooks.d.ts +12 -1
  127. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  128. package/dist/MultiSelector/hooks.js +14 -1
  129. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  130. package/dist/NavMenu/NavHeadingMenu.js +34 -3
  131. package/dist/NumberInput/NumberInput.d.ts +23 -2
  132. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  133. package/dist/NumberInput/NumberInput.js +62 -12
  134. package/dist/Pagination/Pagination.d.ts +1 -1
  135. package/dist/Pagination/Pagination.d.ts.map +1 -1
  136. package/dist/Pagination/Pagination.js +15 -1
  137. package/dist/Popover/Popover.d.ts +18 -2
  138. package/dist/Popover/Popover.d.ts.map +1 -1
  139. package/dist/Popover/Popover.js +5 -2
  140. package/dist/Popover/usePopover.d.ts +38 -3
  141. package/dist/Popover/usePopover.d.ts.map +1 -1
  142. package/dist/Popover/usePopover.js +24 -9
  143. package/dist/PowerSearch/PowerSearch.d.ts +11 -1
  144. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  145. package/dist/PowerSearch/PowerSearch.js +6 -1
  146. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  147. package/dist/ProgressBar/ProgressBar.js +3 -5
  148. package/dist/RadioList/RadioList.d.ts +20 -2
  149. package/dist/RadioList/RadioList.d.ts.map +1 -1
  150. package/dist/RadioList/RadioList.js +105 -9
  151. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  152. package/dist/RadioList/RadioListItem.js +13 -2
  153. package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
  154. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  155. package/dist/SegmentedControl/SegmentedControl.js +78 -44
  156. package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
  157. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  159. package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
  160. package/dist/Selector/Selector.d.ts +24 -1
  161. package/dist/Selector/Selector.d.ts.map +1 -1
  162. package/dist/Selector/Selector.js +122 -43
  163. package/dist/Selector/hooks.d.ts +8 -1
  164. package/dist/Selector/hooks.d.ts.map +1 -1
  165. package/dist/Selector/hooks.js +14 -1
  166. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  167. package/dist/SideNav/SideNavHeading.js +2 -0
  168. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  169. package/dist/SideNav/SideNavItem.js +1 -1
  170. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  171. package/dist/Skeleton/Skeleton.js +8 -2
  172. package/dist/Slider/Slider.d.ts +21 -0
  173. package/dist/Slider/Slider.d.ts.map +1 -1
  174. package/dist/Slider/Slider.js +36 -9
  175. package/dist/Spinner/Spinner.d.ts.map +1 -1
  176. package/dist/Spinner/Spinner.js +1 -1
  177. package/dist/Stack/Stack.d.ts +38 -23
  178. package/dist/Stack/Stack.d.ts.map +1 -1
  179. package/dist/Stack/Stack.js +25 -1
  180. package/dist/Stack/StackItem.d.ts +12 -23
  181. package/dist/Stack/StackItem.d.ts.map +1 -1
  182. package/dist/Stack/StackItem.js +8 -1
  183. package/dist/Switch/Switch.d.ts +23 -2
  184. package/dist/Switch/Switch.d.ts.map +1 -1
  185. package/dist/Switch/Switch.js +41 -11
  186. package/dist/TabList/Tab.d.ts.map +1 -1
  187. package/dist/TabList/Tab.js +6 -0
  188. package/dist/TabList/TabList.d.ts +16 -4
  189. package/dist/TabList/TabList.d.ts.map +1 -1
  190. package/dist/TabList/TabList.js +87 -10
  191. package/dist/TabList/TabListContext.d.ts +5 -0
  192. package/dist/TabList/TabListContext.d.ts.map +1 -1
  193. package/dist/TabList/TabListContext.js +5 -0
  194. package/dist/TabList/TabMenu.d.ts.map +1 -1
  195. package/dist/TabList/TabMenu.js +6 -1
  196. package/dist/Table/BaseTable.d.ts.map +1 -1
  197. package/dist/Table/BaseTable.js +11 -8
  198. package/dist/Table/Table.d.ts.map +1 -1
  199. package/dist/Table/Table.js +10 -1
  200. package/dist/Table/TableCell.d.ts +8 -1
  201. package/dist/Table/TableCell.d.ts.map +1 -1
  202. package/dist/Table/TableCell.js +10 -10
  203. package/dist/Table/TableHeaderCell.d.ts +8 -1
  204. package/dist/Table/TableHeaderCell.d.ts.map +1 -1
  205. package/dist/Table/TableHeaderCell.js +16 -16
  206. package/dist/Table/index.d.ts +2 -1
  207. package/dist/Table/index.d.ts.map +1 -1
  208. package/dist/Table/index.js +2 -2
  209. package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
  210. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  211. package/dist/Table/plugins/pagination/paginateData.js +8 -3
  212. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  213. package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
  214. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  215. package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
  216. package/dist/Table/tableContextMenu.d.ts +33 -0
  217. package/dist/Table/tableContextMenu.d.ts.map +1 -0
  218. package/dist/Table/tableContextMenu.js +133 -0
  219. package/dist/Table/types.d.ts +66 -0
  220. package/dist/Table/types.d.ts.map +1 -1
  221. package/dist/TextArea/TextArea.d.ts +22 -1
  222. package/dist/TextArea/TextArea.d.ts.map +1 -1
  223. package/dist/TextArea/TextArea.js +41 -9
  224. package/dist/TextInput/TextInput.d.ts +23 -2
  225. package/dist/TextInput/TextInput.d.ts.map +1 -1
  226. package/dist/TextInput/TextInput.js +55 -10
  227. package/dist/TimeInput/TimeInput.d.ts +23 -1
  228. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  229. package/dist/TimeInput/TimeInput.js +147 -76
  230. package/dist/Toast/Toast.d.ts.map +1 -1
  231. package/dist/Toast/Toast.js +14 -0
  232. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  233. package/dist/Toast/ToastViewport.js +131 -3
  234. package/dist/Tokenizer/Tokenizer.d.ts +12 -1
  235. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  236. package/dist/Tokenizer/Tokenizer.js +26 -4
  237. package/dist/Toolbar/Toolbar.d.ts +3 -3
  238. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  239. package/dist/Toolbar/Toolbar.js +51 -7
  240. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  241. package/dist/Tooltip/useTooltip.js +56 -9
  242. package/dist/TopNav/TopNavHeading.d.ts +7 -1
  243. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  244. package/dist/TopNav/TopNavHeading.js +8 -0
  245. package/dist/TreeList/TreeList.d.ts +1 -1
  246. package/dist/TreeList/TreeList.d.ts.map +1 -1
  247. package/dist/TreeList/TreeList.js +72 -2
  248. package/dist/TreeList/TreeListItem.d.ts +11 -1
  249. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  250. package/dist/TreeList/TreeListItem.js +51 -12
  251. package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
  252. package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
  253. package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
  254. package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
  255. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  256. package/dist/Typeahead/BaseTypeahead.js +69 -6
  257. package/dist/Typeahead/Typeahead.d.ts +26 -3
  258. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  259. package/dist/Typeahead/Typeahead.js +65 -29
  260. package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
  261. package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
  262. package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
  263. package/dist/VisuallyHidden/index.d.ts +11 -0
  264. package/dist/VisuallyHidden/index.d.ts.map +1 -0
  265. package/dist/VisuallyHidden/index.js +13 -0
  266. package/dist/astryx.css +18 -0
  267. package/dist/astryx.umd.js +55 -55
  268. package/dist/astryx.umd.js.map +4 -4
  269. package/dist/hooks/focusableSelector.d.ts +22 -0
  270. package/dist/hooks/focusableSelector.d.ts.map +1 -0
  271. package/dist/hooks/focusableSelector.js +24 -0
  272. package/dist/hooks/index.d.ts +12 -2
  273. package/dist/hooks/index.d.ts.map +1 -1
  274. package/dist/hooks/index.js +7 -2
  275. package/dist/hooks/useAnnounce.d.ts +40 -0
  276. package/dist/hooks/useAnnounce.d.ts.map +1 -0
  277. package/dist/hooks/useAnnounce.js +142 -0
  278. package/dist/hooks/useClickableContainer.d.ts +16 -1
  279. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  280. package/dist/hooks/useClickableContainer.js +16 -4
  281. package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
  282. package/dist/hooks/useEntryAnimation.js +4 -4
  283. package/dist/hooks/useFocusTrap.d.ts +18 -0
  284. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  285. package/dist/hooks/useFocusTrap.js +87 -3
  286. package/dist/hooks/useGridFocus.d.ts +88 -1
  287. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  288. package/dist/hooks/useGridFocus.js +261 -62
  289. package/dist/hooks/useKeyboardHint.d.ts +82 -0
  290. package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
  291. package/dist/hooks/useKeyboardHint.js +220 -0
  292. package/dist/hooks/useListFocus.d.ts +78 -7
  293. package/dist/hooks/useListFocus.d.ts.map +1 -1
  294. package/dist/hooks/useListFocus.js +305 -52
  295. package/dist/hooks/useLongPress.d.ts +21 -0
  296. package/dist/hooks/useLongPress.d.ts.map +1 -0
  297. package/dist/hooks/useLongPress.js +89 -0
  298. package/dist/hooks/useTreeFocus.d.ts +157 -0
  299. package/dist/hooks/useTreeFocus.d.ts.map +1 -0
  300. package/dist/hooks/useTreeFocus.js +337 -0
  301. package/dist/hooks/useTypeahead.d.ts +63 -0
  302. package/dist/hooks/useTypeahead.d.ts.map +1 -0
  303. package/dist/hooks/useTypeahead.js +117 -0
  304. package/dist/index.d.ts +1 -0
  305. package/dist/index.d.ts.map +1 -1
  306. package/dist/index.js +1 -0
  307. package/dist/utils/dateTypes.d.ts +12 -0
  308. package/dist/utils/dateTypes.d.ts.map +1 -1
  309. package/dist/utils/dateTypes.js +41 -1
  310. package/dist/utils/index.d.ts +4 -0
  311. package/dist/utils/index.d.ts.map +1 -1
  312. package/dist/utils/index.js +3 -1
  313. package/dist/utils/inputAria.d.ts +29 -0
  314. package/dist/utils/inputAria.d.ts.map +1 -0
  315. package/dist/utils/inputAria.js +30 -0
  316. package/dist/utils/timeParser.d.ts.map +1 -1
  317. package/dist/utils/timeParser.js +5 -2
  318. package/docs.mjs +2 -2
  319. package/package.json +12 -8
  320. package/src/Avatar/Avatar.test.tsx +37 -0
  321. package/src/Avatar/Avatar.tsx +10 -5
  322. package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
  323. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
  324. package/src/Button/Button.tsx +3 -16
  325. package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
  326. package/src/ButtonGroup/ButtonGroup.tsx +0 -1
  327. package/src/Calendar/Calendar.doc.mjs +4 -4
  328. package/src/Calendar/Calendar.test.tsx +168 -30
  329. package/src/Calendar/Calendar.tsx +121 -66
  330. package/src/Calendar/hooks/index.ts +0 -6
  331. package/src/Calendar/index.ts +1 -3
  332. package/src/Calendar/styles.ts +4 -9
  333. package/src/Carousel/Carousel.doc.mjs +7 -1
  334. package/src/Carousel/Carousel.test.tsx +20 -0
  335. package/src/Carousel/Carousel.tsx +16 -1
  336. package/src/Center/Center.doc.mjs +12 -2
  337. package/src/Center/Center.tsx +28 -3
  338. package/src/Chat/ChatComposerInput.test.tsx +26 -7
  339. package/src/Chat/ChatComposerInput.tsx +0 -1
  340. package/src/Chat/ChatDictationButton.doc.mjs +1 -1
  341. package/src/Chat/ChatMessageList.doc.mjs +8 -0
  342. package/src/Chat/ChatMessageList.test.tsx +18 -0
  343. package/src/Chat/ChatMessageList.tsx +16 -0
  344. package/src/Chat/useTriggerMenu.tsx +22 -4
  345. package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
  346. package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
  347. package/src/CheckboxInput/CheckboxInput.tsx +78 -6
  348. package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
  349. package/src/CheckboxList/CheckboxList.test.tsx +192 -26
  350. package/src/CheckboxList/CheckboxList.tsx +56 -3
  351. package/src/CheckboxList/CheckboxListContext.tsx +7 -0
  352. package/src/CheckboxList/CheckboxListItem.tsx +0 -3
  353. package/src/Citation/Citation.doc.mjs +10 -0
  354. package/src/Citation/Citation.test.tsx +121 -0
  355. package/src/Citation/Citation.tsx +15 -3
  356. package/src/CodeBlock/CodeBlock.test.tsx +115 -0
  357. package/src/CodeBlock/CodeBlock.tsx +63 -33
  358. package/src/CommandPalette/CommandPalette.test.tsx +47 -1
  359. package/src/CommandPalette/CommandPalette.tsx +9 -21
  360. package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
  361. package/src/ContextMenu/ContextMenu.test.tsx +155 -1
  362. package/src/ContextMenu/ContextMenu.tsx +113 -16
  363. package/src/DateInput/DateInput.doc.mjs +286 -56
  364. package/src/DateInput/DateInput.test.tsx +248 -2
  365. package/src/DateInput/DateInput.tsx +196 -100
  366. package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
  367. package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
  368. package/src/DateRangeInput/DateRangeInput.tsx +63 -5
  369. package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
  370. package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
  371. package/src/DateTimeInput/DateTimeInput.tsx +125 -17
  372. package/src/Dialog/Dialog.doc.mjs +2 -2
  373. package/src/Dialog/Dialog.tsx +12 -0
  374. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
  375. package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
  376. package/src/DropdownMenu/DropdownMenu.tsx +52 -18
  377. package/src/Field/Field.doc.mjs +59 -18
  378. package/src/Field/Field.test.tsx +32 -0
  379. package/src/Field/Field.tsx +23 -5
  380. package/src/Field/FieldLabel.tsx +55 -17
  381. package/src/FileInput/FileInput.doc.mjs +17 -0
  382. package/src/FileInput/FileInput.test.tsx +283 -49
  383. package/src/FileInput/FileInput.tsx +76 -4
  384. package/src/Grid/Grid.doc.mjs +17 -4
  385. package/src/Grid/Grid.test.tsx +43 -30
  386. package/src/Grid/Grid.tsx +38 -3
  387. package/src/Icon/Icon.doc.mjs +3 -3
  388. package/src/InputGroup/InputGroup.doc.mjs +111 -23
  389. package/src/InputGroup/InputGroup.test.tsx +257 -60
  390. package/src/InputGroup/InputGroup.tsx +23 -5
  391. package/src/InputGroup/InputGroupContext.ts +9 -4
  392. package/src/InputGroup/groupStyles.ts +7 -1
  393. package/src/InputGroup/index.ts +1 -0
  394. package/src/Kbd/Kbd.test.tsx +22 -4
  395. package/src/Kbd/Kbd.tsx +35 -3
  396. package/src/Layer/layerAnimations.stylex.ts +20 -4
  397. package/src/Layer/useLayer.doc.mjs +5 -0
  398. package/src/Layer/useLayer.test.tsx +111 -0
  399. package/src/Layer/useLayer.tsx +90 -9
  400. package/src/Layout/Layout.tsx +8 -16
  401. package/src/Layout/LayoutFooter.doc.mjs +4 -4
  402. package/src/Layout/LayoutFooter.tsx +3 -3
  403. package/src/Layout/LayoutHeader.doc.mjs +4 -4
  404. package/src/Layout/LayoutHeader.tsx +3 -3
  405. package/src/Layout/LayoutPanel.tsx +3 -3
  406. package/src/Layout/padding.stylex.ts +52 -0
  407. package/src/Lightbox/Lightbox.doc.mjs +9 -0
  408. package/src/Lightbox/Lightbox.test.tsx +53 -5
  409. package/src/Lightbox/Lightbox.tsx +9 -4
  410. package/src/Link/Link.doc.mjs +14 -0
  411. package/src/Link/Link.test.tsx +50 -0
  412. package/src/Link/Link.tsx +39 -4
  413. package/src/Markdown/Markdown.test.tsx +11 -0
  414. package/src/Markdown/Markdown.tsx +7 -0
  415. package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
  416. package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
  417. package/src/MoreMenu/MoreMenu.tsx +0 -9
  418. package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
  419. package/src/MultiSelector/MultiSelector.test.tsx +375 -8
  420. package/src/MultiSelector/MultiSelector.tsx +194 -48
  421. package/src/MultiSelector/hooks.ts +27 -0
  422. package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
  423. package/src/NavMenu/NavHeadingMenu.tsx +50 -3
  424. package/src/NumberInput/NumberInput.doc.mjs +17 -0
  425. package/src/NumberInput/NumberInput.test.tsx +242 -40
  426. package/src/NumberInput/NumberInput.tsx +89 -11
  427. package/src/Pagination/Pagination.doc.mjs +3 -3
  428. package/src/Pagination/Pagination.test.tsx +117 -5
  429. package/src/Pagination/Pagination.tsx +21 -1
  430. package/src/Popover/Popover.doc.mjs +26 -0
  431. package/src/Popover/Popover.test.tsx +121 -0
  432. package/src/Popover/Popover.tsx +23 -2
  433. package/src/Popover/usePopover.doc.mjs +9 -3
  434. package/src/Popover/usePopover.tsx +70 -12
  435. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  436. package/src/PowerSearch/PowerSearch.test.tsx +97 -1
  437. package/src/PowerSearch/PowerSearch.tsx +16 -3
  438. package/src/ProgressBar/ProgressBar.test.tsx +34 -26
  439. package/src/ProgressBar/ProgressBar.tsx +3 -4
  440. package/src/RadioList/RadioList.doc.mjs +9 -0
  441. package/src/RadioList/RadioList.test.tsx +252 -16
  442. package/src/RadioList/RadioList.tsx +166 -10
  443. package/src/RadioList/RadioListItem.tsx +14 -2
  444. package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
  445. package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
  446. package/src/SegmentedControl/SegmentedControl.tsx +102 -54
  447. package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
  448. package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
  449. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  450. package/src/Selector/Selector.doc.mjs +26 -0
  451. package/src/Selector/Selector.test.tsx +387 -15
  452. package/src/Selector/Selector.tsx +175 -67
  453. package/src/Selector/hooks.ts +23 -0
  454. package/src/SideNav/SideNav.test.tsx +48 -0
  455. package/src/SideNav/SideNavHeading.tsx +8 -2
  456. package/src/SideNav/SideNavItem.tsx +2 -4
  457. package/src/Skeleton/Skeleton.test.tsx +25 -0
  458. package/src/Skeleton/Skeleton.tsx +11 -1
  459. package/src/Slider/Slider.doc.mjs +15 -0
  460. package/src/Slider/Slider.test.tsx +155 -2
  461. package/src/Slider/Slider.tsx +53 -5
  462. package/src/Spinner/Spinner.tsx +7 -1
  463. package/src/Stack/Stack.doc.mjs +77 -0
  464. package/src/Stack/Stack.test.tsx +55 -5
  465. package/src/Stack/Stack.tsx +73 -24
  466. package/src/Stack/StackItem.test.tsx +23 -0
  467. package/src/Stack/StackItem.tsx +20 -23
  468. package/src/Switch/Switch.doc.mjs +15 -0
  469. package/src/Switch/Switch.test.tsx +162 -27
  470. package/src/Switch/Switch.tsx +61 -21
  471. package/src/TabList/Tab.tsx +6 -0
  472. package/src/TabList/TabList.doc.mjs +6 -0
  473. package/src/TabList/TabList.test.tsx +251 -0
  474. package/src/TabList/TabList.tsx +103 -12
  475. package/src/TabList/TabListContext.ts +7 -3
  476. package/src/TabList/TabMenu.tsx +6 -3
  477. package/src/Table/BaseTable.tsx +21 -17
  478. package/src/Table/Table.doc.mjs +2 -0
  479. package/src/Table/Table.test.tsx +10 -0
  480. package/src/Table/Table.tsx +8 -0
  481. package/src/Table/TableCell.tsx +25 -23
  482. package/src/Table/TableHeaderCell.tsx +28 -29
  483. package/src/Table/index.ts +3 -2
  484. package/src/Table/plugins/pagination/paginateData.ts +10 -3
  485. package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
  486. package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
  487. package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
  488. package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
  489. package/src/Table/tableContextMenu.test.tsx +157 -0
  490. package/src/Table/tableContextMenu.tsx +142 -0
  491. package/src/Table/types.ts +74 -0
  492. package/src/Table/useTableColumnResize.doc.mjs +3 -3
  493. package/src/Table/useTableStickyColumns.doc.mjs +2 -2
  494. package/src/Text/Text.doc.mjs +18 -18
  495. package/src/TextArea/TextArea.doc.mjs +17 -0
  496. package/src/TextArea/TextArea.test.tsx +167 -35
  497. package/src/TextArea/TextArea.tsx +62 -15
  498. package/src/TextInput/TextInput.doc.mjs +17 -0
  499. package/src/TextInput/TextInput.test.tsx +168 -34
  500. package/src/TextInput/TextInput.tsx +77 -9
  501. package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
  502. package/src/TimeInput/TimeInput.doc.mjs +340 -60
  503. package/src/TimeInput/TimeInput.test.tsx +255 -7
  504. package/src/TimeInput/TimeInput.tsx +176 -70
  505. package/src/Timestamp/Timestamp.doc.mjs +19 -19
  506. package/src/Toast/Toast.tsx +14 -0
  507. package/src/Toast/ToastViewport.test.tsx +214 -0
  508. package/src/Toast/ToastViewport.tsx +167 -21
  509. package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
  510. package/src/Tokenizer/Tokenizer.test.tsx +105 -1
  511. package/src/Tokenizer/Tokenizer.tsx +37 -1
  512. package/src/Toolbar/Toolbar.test.tsx +109 -6
  513. package/src/Toolbar/Toolbar.tsx +59 -5
  514. package/src/Tooltip/Tooltip.test.tsx +68 -0
  515. package/src/Tooltip/useTooltip.tsx +55 -8
  516. package/src/TopNav/TopNav.test.tsx +50 -0
  517. package/src/TopNav/TopNavHeading.tsx +17 -1
  518. package/src/TreeList/TreeList.test.tsx +295 -6
  519. package/src/TreeList/TreeList.tsx +73 -1
  520. package/src/TreeList/TreeListItem.tsx +51 -5
  521. package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
  522. package/src/Typeahead/BaseTypeahead.tsx +93 -9
  523. package/src/Typeahead/Typeahead.doc.mjs +141 -30
  524. package/src/Typeahead/Typeahead.test.tsx +331 -1
  525. package/src/Typeahead/Typeahead.tsx +105 -33
  526. package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
  527. package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
  528. package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
  529. package/src/VisuallyHidden/index.ts +15 -0
  530. package/src/docs-script.test.mjs +50 -0
  531. package/src/hooks/focusableSelector.ts +25 -0
  532. package/src/hooks/index.ts +28 -2
  533. package/src/hooks/useAnnounce.test.tsx +101 -0
  534. package/src/hooks/useAnnounce.ts +168 -0
  535. package/src/hooks/useClickableContainer.ts +16 -4
  536. package/src/hooks/useEntryAnimation.ts +16 -4
  537. package/src/hooks/useFocusTrap.test.tsx +132 -0
  538. package/src/hooks/useFocusTrap.ts +98 -4
  539. package/src/hooks/useGridFocus.doc.mjs +40 -2
  540. package/src/hooks/useGridFocus.test.tsx +132 -0
  541. package/src/hooks/useGridFocus.ts +343 -67
  542. package/src/hooks/useKeyboardHint.doc.mjs +101 -0
  543. package/src/hooks/useKeyboardHint.test.tsx +70 -0
  544. package/src/hooks/useKeyboardHint.tsx +332 -0
  545. package/src/hooks/useListFocus.doc.mjs +50 -10
  546. package/src/hooks/useListFocus.test.tsx +375 -0
  547. package/src/hooks/useListFocus.ts +395 -57
  548. package/src/hooks/useLongPress.test.tsx +134 -0
  549. package/src/hooks/useLongPress.ts +119 -0
  550. package/src/hooks/useTreeFocus.doc.mjs +140 -0
  551. package/src/hooks/useTreeFocus.test.tsx +214 -0
  552. package/src/hooks/useTreeFocus.ts +559 -0
  553. package/src/hooks/useTypeahead.test.tsx +109 -0
  554. package/src/hooks/useTypeahead.ts +183 -0
  555. package/src/index.ts +1 -0
  556. package/src/theme/derivedVarRegistry.test.ts +10 -5
  557. package/src/utils/dateTypes.test.ts +40 -0
  558. package/src/utils/dateTypes.ts +40 -0
  559. package/src/utils/index.ts +9 -0
  560. package/src/utils/inputAria.test.ts +39 -0
  561. package/src/utils/inputAria.ts +58 -0
  562. package/src/utils/timeParser.test.ts +10 -0
  563. package/src/utils/timeParser.ts +5 -2
  564. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
  565. package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
  566. package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
  567. package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
@@ -9,41 +9,56 @@
9
9
  * SYNC: When CheckboxInput.tsx changes, update tests to match new behavior
10
10
  */
11
11
 
12
- import {describe, it, expect, vi} from 'vitest';
13
- import {render, screen} from '@testing-library/react';
12
+ import {describe, it, expect, vi, beforeEach} from 'vitest';
13
+ import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {CheckboxInput} from './CheckboxInput';
16
16
 
17
+ // Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
18
+ // reflects its open state via a `popover-open` attribute the tests can assert.
19
+ beforeEach(() => {
20
+ HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
21
+ this.setAttribute('popover-open', '');
22
+ const event = new Event('toggle', {bubbles: false});
23
+ Object.defineProperty(event, 'newState', {value: 'open'});
24
+ this.dispatchEvent(event);
25
+ });
26
+ HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
27
+ this.removeAttribute('popover-open');
28
+ const event = new Event('toggle', {bubbles: false});
29
+ Object.defineProperty(event, 'newState', {value: 'closed'});
30
+ this.dispatchEvent(event);
31
+ });
32
+ const originalMatches = HTMLElement.prototype.matches;
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ (HTMLElement.prototype as any).matches = function (
35
+ selector: string,
36
+ ): boolean {
37
+ if (selector === ':popover-open') {
38
+ return this.hasAttribute('popover-open');
39
+ }
40
+ return originalMatches.call(this, selector);
41
+ };
42
+ });
43
+
17
44
  describe('CheckboxInput', () => {
18
45
  it('renders with label', () => {
19
46
  render(
20
- <CheckboxInput
21
- label="Accept terms"
22
- value={false}
23
- onChange={() => {}}
24
- />,
47
+ <CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
25
48
  );
26
49
  expect(screen.getByLabelText('Accept terms')).toBeInTheDocument();
27
50
  });
28
51
 
29
52
  it('renders as unchecked by default', () => {
30
53
  render(
31
- <CheckboxInput
32
- label="Accept terms"
33
- value={false}
34
- onChange={() => {}}
35
- />,
54
+ <CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
36
55
  );
37
56
  expect(screen.getByRole('checkbox')).not.toBeChecked();
38
57
  });
39
58
 
40
59
  it('renders as checked when value prop is true', () => {
41
60
  render(
42
- <CheckboxInput
43
- label="Accept terms"
44
- value={true}
45
- onChange={() => {}}
46
- />,
61
+ <CheckboxInput label="Accept terms" value={true} onChange={() => {}} />,
47
62
  );
48
63
  expect(screen.getByRole('checkbox')).toBeChecked();
49
64
  });
@@ -182,11 +197,7 @@ describe('CheckboxInput', () => {
182
197
 
183
198
  it('shows label visually by default', () => {
184
199
  render(
185
- <CheckboxInput
186
- label="Accept terms"
187
- value={false}
188
- onChange={() => {}}
189
- />,
200
+ <CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
190
201
  );
191
202
  const label = screen.getByText('Accept terms');
192
203
  expect(label).toBeVisible();
@@ -204,7 +215,7 @@ describe('CheckboxInput', () => {
204
215
  expect(screen.getByRole('checkbox')).toHaveAttribute('aria-busy', 'true');
205
216
  });
206
217
 
207
- it('sets aria-checked="mixed" for indeterminate state', () => {
218
+ it('exposes indeterminate state via the native indeterminate property', () => {
208
219
  render(
209
220
  <CheckboxInput
210
221
  label="Select all"
@@ -212,10 +223,15 @@ describe('CheckboxInput', () => {
212
223
  onChange={() => {}}
213
224
  />,
214
225
  );
215
- expect(screen.getByRole('checkbox')).toHaveAttribute(
216
- 'aria-checked',
217
- 'mixed',
218
- );
226
+ const checkbox = screen.getByRole('checkbox');
227
+ // Native checkboxes expose mixed state through the DOM indeterminate
228
+ // property, which browsers map to aria-checked="mixed". A redundant
229
+ // aria-checked attribute is intentionally NOT set (forms-16).
230
+ expect(checkbox).toBeInstanceOf(HTMLInputElement);
231
+ if (checkbox instanceof HTMLInputElement) {
232
+ expect(checkbox.indeterminate).toBe(true);
233
+ }
234
+ expect(checkbox).not.toHaveAttribute('aria-checked');
219
235
  });
220
236
 
221
237
  it('renders semantic labelIcon names as icons', () => {
@@ -247,4 +263,133 @@ describe('CheckboxInput', () => {
247
263
  'true',
248
264
  );
249
265
  });
266
+
267
+ describe('disabledMessage', () => {
268
+ const h = {hidden: true} as const;
269
+
270
+ function getRow(): HTMLElement {
271
+ return screen.getByRole('checkbox', h).closest('div')!.parentElement!;
272
+ }
273
+
274
+ it('shows the reason tooltip on hover when disabled with a reason', async () => {
275
+ render(
276
+ <CheckboxInput
277
+ label="Accept terms"
278
+ value={false}
279
+ onChange={() => {}}
280
+ isDisabled
281
+ disabledMessage="Terms are managed by your administrator"
282
+ />,
283
+ );
284
+ const tooltip = screen.getByRole('tooltip', h);
285
+ expect(tooltip).toHaveTextContent(
286
+ 'Terms are managed by your administrator',
287
+ );
288
+ fireEvent.mouseEnter(getRow());
289
+ await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
290
+ fireEvent.mouseLeave(getRow());
291
+ await waitFor(() => expect(tooltip).not.toHaveAttribute('popover-open'));
292
+ });
293
+
294
+ it('shows the reason tooltip on keyboard focus', async () => {
295
+ const user = userEvent.setup();
296
+ render(
297
+ <CheckboxInput
298
+ label="Accept terms"
299
+ value={false}
300
+ onChange={() => {}}
301
+ isDisabled
302
+ disabledMessage="Terms are managed by your administrator"
303
+ />,
304
+ );
305
+ const tooltip = screen.getByRole('tooltip', h);
306
+ await user.tab();
307
+ expect(screen.getByRole('checkbox', h)).toHaveFocus();
308
+ await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
309
+ });
310
+
311
+ it('does not render a tooltip when not disabled', () => {
312
+ render(
313
+ <CheckboxInput
314
+ label="Accept terms"
315
+ value={false}
316
+ onChange={() => {}}
317
+ disabledMessage="Terms are managed by your administrator"
318
+ />,
319
+ );
320
+ expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
321
+ });
322
+
323
+ it('does not render a tooltip when disabled without a reason', () => {
324
+ render(
325
+ <CheckboxInput
326
+ label="Accept terms"
327
+ value={false}
328
+ onChange={() => {}}
329
+ isDisabled
330
+ />,
331
+ );
332
+ expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
333
+ });
334
+
335
+ it('keeps the checkbox focusable via aria-disabled when a reason is provided', () => {
336
+ render(
337
+ <CheckboxInput
338
+ label="Accept terms"
339
+ value={false}
340
+ onChange={() => {}}
341
+ isDisabled
342
+ disabledMessage="Terms are managed by your administrator"
343
+ />,
344
+ );
345
+ const checkbox = screen.getByRole('checkbox', h);
346
+ expect(checkbox).not.toBeDisabled();
347
+ expect(checkbox).toHaveAttribute('aria-disabled', 'true');
348
+ });
349
+
350
+ it('links the reason tooltip via aria-describedby', () => {
351
+ render(
352
+ <CheckboxInput
353
+ label="Accept terms"
354
+ value={false}
355
+ onChange={() => {}}
356
+ isDisabled
357
+ disabledMessage="Terms are managed by your administrator"
358
+ />,
359
+ );
360
+ const checkbox = screen.getByRole('checkbox', h);
361
+ const tooltip = screen.getByRole('tooltip', h);
362
+ expect(checkbox.getAttribute('aria-describedby')).toContain(tooltip.id);
363
+ });
364
+
365
+ it('blocks toggling while focusable-disabled', async () => {
366
+ const user = userEvent.setup();
367
+ const onChange = vi.fn();
368
+ render(
369
+ <CheckboxInput
370
+ label="Accept terms"
371
+ value={false}
372
+ onChange={onChange}
373
+ isDisabled
374
+ disabledMessage="Terms are managed by your administrator"
375
+ />,
376
+ );
377
+ const checkbox = screen.getByRole('checkbox', h);
378
+ await user.click(checkbox);
379
+ expect(onChange).not.toHaveBeenCalled();
380
+ expect(checkbox).not.toBeChecked();
381
+ });
382
+
383
+ it('remains natively disabled when disabled without a reason', () => {
384
+ render(
385
+ <CheckboxInput
386
+ label="Accept terms"
387
+ value={false}
388
+ onChange={() => {}}
389
+ isDisabled
390
+ />,
391
+ );
392
+ expect(screen.getByRole('checkbox')).toBeDisabled();
393
+ });
394
+ });
250
395
  });
@@ -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
  };