@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 Selector.tsx
7
- * @input Uses React, StyleX, usePopover, Icon
7
+ * @input Uses React, StyleX, usePopover, useTooltip, Icon
8
8
  * @output Exports Selector component
9
9
  * @position Core implementation; consumed by index.ts
10
10
  *
@@ -27,6 +27,7 @@ import React, {
27
27
  } from 'react';
28
28
  import * as stylex from '@stylexjs/stylex';
29
29
  import {usePopover} from '../Popover/usePopover';
30
+ import {useTooltip} from '../Tooltip';
30
31
  import {Icon, renderIconSlot, type IconType} from '../Icon';
31
32
  import type {IconName} from '../Icon';
32
33
  import {
@@ -369,6 +370,28 @@ interface SelectorPropsBase<
369
370
  */
370
371
  isDisabled?: boolean;
371
372
 
373
+ /**
374
+ * Explains why the selector is disabled. When set together with
375
+ * `isDisabled`, the selector shows a tooltip with this text on hover and
376
+ * keyboard focus, and the trigger stays focusable (via `aria-disabled`)
377
+ * so the reason is discoverable by keyboard and assistive technology.
378
+ * Activation stays blocked.
379
+ *
380
+ * Use this instead of wrapping a disabled selector in `Tooltip` — disabled
381
+ * controls don't emit the pointer events an external tooltip needs.
382
+ *
383
+ * @example
384
+ * ```
385
+ * <Selector
386
+ * label="Owner"
387
+ * options={owners}
388
+ * isDisabled
389
+ * disabledMessage="You need the Editor role to change this"
390
+ * />
391
+ * ```
392
+ */
393
+ disabledMessage?: string;
394
+
372
395
  /**
373
396
  * The options to display in the selector.
374
397
  * Can be strings, objects, dividers, or sections.
@@ -474,34 +497,30 @@ type SelectorPropsNonClearable<
474
497
  changeAction?: (value: string) => void | Promise<void>;
475
498
  };
476
499
 
477
- type SelectorPropsClearable<
478
- T extends SelectorOptionType = SelectorOptionType,
479
- > = SelectorPropsBase<T> & {
480
- /**
481
- * Whether to show a clear button when a value is selected.
482
- * When clicked, resets the value to `null` and returns focus to the trigger.
483
- *
484
- * When enabled, `value` and `onChange` widen to include `null`.
485
- */
486
- hasClear: true;
487
- value: string | null;
488
- onChange?: (value: string | null) => void;
489
- changeAction?: (value: string | null) => void | Promise<void>;
490
- };
491
-
492
- export type SelectorProps<
493
- T extends SelectorOptionType = SelectorOptionType,
494
- > = SelectorPropsNonClearable<T> | SelectorPropsClearable<T>;
500
+ type SelectorPropsClearable<T extends SelectorOptionType = SelectorOptionType> =
501
+ SelectorPropsBase<T> & {
502
+ /**
503
+ * Whether to show a clear button when a value is selected.
504
+ * When clicked, resets the value to `null` and returns focus to the trigger.
505
+ *
506
+ * When enabled, `value` and `onChange` widen to include `null`.
507
+ */
508
+ hasClear: true;
509
+ value: string | null;
510
+ onChange?: (value: string | null) => void;
511
+ changeAction?: (value: string | null) => void | Promise<void>;
512
+ };
513
+
514
+ export type SelectorProps<T extends SelectorOptionType = SelectorOptionType> =
515
+ | SelectorPropsNonClearable<T>
516
+ | SelectorPropsClearable<T>;
495
517
 
496
518
  /**
497
519
  * Default option renderer
498
520
  */
499
521
  function DefaultOption({option}: {option: SelectorOptionData}) {
500
522
  return (
501
- <SelectorOption
502
- icon={option.icon}
503
- label={option.label ?? option.value}
504
- />
523
+ <SelectorOption icon={option.icon} label={option.label ?? option.value} />
505
524
  );
506
525
  }
507
526
 
@@ -529,6 +548,7 @@ export function Selector<T extends SelectorOptionType>(
529
548
  isOptional = false,
530
549
  isRequired = false,
531
550
  isDisabled = false,
551
+ disabledMessage,
532
552
  options,
533
553
  value,
534
554
  onChange,
@@ -571,11 +591,26 @@ export function Selector<T extends SelectorOptionType>(
571
591
  const [optimisticValue, setOptimisticValue] = useOptimistic(normalizedValue);
572
592
  const isBusy = isLoading || optimisticValue !== normalizedValue;
573
593
 
594
+ // Disabled-reason tooltip. Disabled controls swallow pointer events, so the
595
+ // tooltip listeners attach to the trigger container (which already exists)
596
+ // and the trigger button stays perceivable via aria-disabled instead of the
597
+ // disabled attribute. Activation is blocked by the isDisabled guards in
598
+ // useCombobox (onTriggerClick / onKeyDown).
599
+ const showsDisabledMessage = isDisabled && !!disabledMessage;
600
+ const disabledMessageTooltip = useTooltip({
601
+ placement: 'above',
602
+ // The container div is not naturally focusable; focusin bubbles up from
603
+ // the trigger button, so always attach focus listeners.
604
+ focusTrigger: 'always',
605
+ isEnabled: showsDisabledMessage,
606
+ });
607
+
574
608
  // Build aria-describedby
575
609
  const ariaDescribedBy =
576
610
  [
577
611
  description ? descriptionId : null,
578
612
  status?.message ? statusMessageId : null,
613
+ showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
579
614
  ]
580
615
  .filter(Boolean)
581
616
  .join(' ') || undefined;
@@ -622,6 +657,9 @@ export function Selector<T extends SelectorOptionType>(
622
657
  hasLightDismiss: true,
623
658
  hasCloseButton: false,
624
659
  hasAutoFocus: false,
660
+ // The popup's own role="listbox" is the exposed semantics; the trigger
661
+ // keeps DOM focus, so wrapping it in a modal dialog would misrepresent it.
662
+ role: 'none',
625
663
  });
626
664
 
627
665
  // Open dropdown on mount when isDefaultOpen is true
@@ -653,6 +691,18 @@ export function Selector<T extends SelectorOptionType>(
653
691
  ? {marginBlockStart: `-${selectedItemOffset}px`}
654
692
  : undefined;
655
693
 
694
+ // Clear the current value. Shared by the clear button and the keyboard
695
+ // Delete/Backspace path so clearing is reachable without a mouse.
696
+ const clearValue = useCallback(() => {
697
+ onChange?.(null);
698
+ if (changeAction) {
699
+ startTransition(async () => {
700
+ setOptimisticValue(undefined);
701
+ await changeAction(null);
702
+ });
703
+ }
704
+ }, [onChange, changeAction, startTransition, setOptimisticValue]);
705
+
656
706
  // Selector behavior (keyboard nav, typeahead, selection)
657
707
  const {
658
708
  highlightedIndex,
@@ -689,22 +739,30 @@ export function Selector<T extends SelectorOptionType>(
689
739
  },
690
740
  [onChange, changeAction, startTransition, setOptimisticValue],
691
741
  ),
742
+ onClear: hasClear ? clearValue : undefined,
692
743
  listboxId,
693
744
  });
694
745
 
746
+ // Keep the highlighted option visible during keyboard navigation. The
747
+ // listbox is a fixed-height scroll container, so without this the virtual
748
+ // cursor walks off-screen once navigation passes the visible window. Mirrors
749
+ // CommandPaletteItem's scrollIntoView({block: 'nearest'}) behavior.
750
+ useEffect(() => {
751
+ if (!popover.isOpen || highlightedIndex < 0) {
752
+ return;
753
+ }
754
+ document
755
+ .getElementById(getItemId(highlightedIndex))
756
+ ?.scrollIntoView?.({block: 'nearest'});
757
+ }, [popover.isOpen, highlightedIndex, getItemId]);
758
+
695
759
  // Handle clear button click
696
760
  const handleClear = useCallback(
697
761
  (e: React.MouseEvent) => {
698
762
  e.stopPropagation(); // Don't open dropdown
699
- onChange?.(null);
700
- if (changeAction) {
701
- startTransition(async () => {
702
- setOptimisticValue(undefined);
703
- await changeAction(null);
704
- });
705
- }
763
+ clearValue();
706
764
  },
707
- [onChange, changeAction, startTransition, setOptimisticValue],
765
+ [clearValue],
708
766
  );
709
767
 
710
768
  // Render search input
@@ -717,16 +775,30 @@ export function Selector<T extends SelectorOptionType>(
717
775
  <input
718
776
  ref={searchRef}
719
777
  id={searchId}
720
- role="searchbox"
778
+ // When hasSearch is set, focus moves into this input on open, so it —
779
+ // not the trigger — must be the combobox that reports the highlighted
780
+ // option via aria-activedescendant (comboboxes-4). A bare searchbox
781
+ // left the highlight silent to screen readers.
782
+ role="combobox"
783
+ aria-expanded={popover.isOpen}
721
784
  aria-controls={listboxId}
785
+ aria-autocomplete="list"
786
+ aria-activedescendant={
787
+ popover.isOpen && highlightedIndex >= 0
788
+ ? getItemId(highlightedIndex)
789
+ : undefined
790
+ }
722
791
  aria-label="Search options"
723
792
  type="text"
724
793
  value={searchQuery}
725
794
  onChange={e => setSearchQuery(e.target.value)}
726
795
  onKeyDown={e => {
796
+ // Arrow keys navigate options; Enter selects; Escape/Tab close.
797
+ // Home/End are left to the input for caret movement.
727
798
  if (
728
799
  e.key === 'ArrowDown' ||
729
800
  e.key === 'ArrowUp' ||
801
+ e.key === 'Enter' ||
730
802
  e.key === 'Escape' ||
731
803
  e.key === 'Tab'
732
804
  ) {
@@ -745,6 +817,9 @@ export function Selector<T extends SelectorOptionType>(
745
817
  searchQuery,
746
818
  searchPlaceholder,
747
819
  onKeyDown,
820
+ popover.isOpen,
821
+ highlightedIndex,
822
+ getItemId,
748
823
  ]);
749
824
 
750
825
  // Render an individual item
@@ -812,9 +887,7 @@ export function Selector<T extends SelectorOptionType>(
812
887
  const option = options[i];
813
888
 
814
889
  if (isDivider(option)) {
815
- elements.push(
816
- <Divider key={`divider-${i}`} xstyle={styles.divider} />,
817
- );
890
+ elements.push(<Divider key={`divider-${i}`} xstyle={styles.divider} />);
818
891
  } else if (isSection(option)) {
819
892
  const sectionItems: ReactNode[] = [];
820
893
  for (const opt of option.options) {
@@ -868,6 +941,10 @@ export function Selector<T extends SelectorOptionType>(
868
941
  <div
869
942
  ref={el => {
870
943
  popover.triggerRef(el);
944
+ // Anchor + hover/focus listeners for the disabled-message tooltip.
945
+ // Handlers are gated internally by isEnabled, and anchor names
946
+ // compose, so attaching unconditionally is safe.
947
+ disabledMessageTooltip.ref(el);
871
948
  }}
872
949
  onClick={onTriggerClick}
873
950
  data-testid={testId}
@@ -892,13 +969,16 @@ export function Selector<T extends SelectorOptionType>(
892
969
  ref={triggerRef}
893
970
  id={triggerId}
894
971
  type="button"
895
- role="combobox"
972
+ // In hasSearch mode the popup's search input is the combobox (it owns
973
+ // focus + aria-activedescendant, comboboxes-4), so the trigger is a
974
+ // plain button that opens the listbox — not a second combobox.
975
+ role={hasSearch ? undefined : 'combobox'}
896
976
  {...rest}
897
977
  aria-haspopup="listbox"
898
978
  aria-expanded={popover.isOpen}
899
979
  aria-controls={listboxId}
900
980
  aria-activedescendant={
901
- popover.isOpen && highlightedIndex >= 0
981
+ !hasSearch && popover.isOpen && highlightedIndex >= 0
902
982
  ? getItemId(highlightedIndex)
903
983
  : undefined
904
984
  }
@@ -906,9 +986,13 @@ export function Selector<T extends SelectorOptionType>(
906
986
  aria-required={isRequired ? 'true' : undefined}
907
987
  aria-invalid={status?.type === 'error' ? 'true' : undefined}
908
988
  aria-busy={isBusy || undefined}
909
- disabled={isDisabled}
989
+ // With a disabledMessage the trigger keeps focusability via
990
+ // aria-disabled so the reason is focus-discoverable; activation is
991
+ // still blocked by the isDisabled guards in useCombobox.
992
+ disabled={isDisabled && !showsDisabledMessage}
993
+ aria-disabled={showsDisabledMessage ? 'true' : undefined}
910
994
  onKeyDown={onKeyDown}
911
- tabIndex={-1}
995
+ tabIndex={isDisabled && !showsDisabledMessage ? -1 : 0}
912
996
  {...stylex.props(styles.trigger)}>
913
997
  <span {...stylex.props(styles.triggerLabel)}>
914
998
  {selectedItem?.label ?? placeholder}
@@ -918,7 +1002,6 @@ export function Selector<T extends SelectorOptionType>(
918
1002
  {hasClear && value != null && !isDisabled && (
919
1003
  <button
920
1004
  type="button"
921
- tabIndex={-1}
922
1005
  onClick={handleClear}
923
1006
  aria-label={`Clear ${label}`}
924
1007
  {...stylex.props(styles.clearButton)}>
@@ -976,6 +1059,9 @@ export function Selector<T extends SelectorOptionType>(
976
1059
  style: popoverOffsetStyle,
977
1060
  },
978
1061
  )}
1062
+
1063
+ {showsDisabledMessage &&
1064
+ disabledMessageTooltip.renderTooltip(disabledMessage)}
979
1065
  </Field>
980
1066
  );
981
1067
  }
@@ -138,6 +138,13 @@ interface UseComboboxOptions {
138
138
  onOpen: () => void;
139
139
  onClose: () => void;
140
140
  onSelect?: (value: string) => void;
141
+ /**
142
+ * Clear the current value. When provided, pressing Delete or Backspace on the
143
+ * closed trigger clears the selection — a keyboard equivalent of the clear
144
+ * button, so clearing is not mouse-only. No-op when the popup is open (arrow
145
+ * navigation owns those keys there) or when there is no value.
146
+ */
147
+ onClear?: () => void;
141
148
  listboxId: string;
142
149
  }
143
150
 
@@ -163,6 +170,7 @@ export function useCombobox({
163
170
  onOpen,
164
171
  onClose,
165
172
  onSelect,
173
+ onClear,
166
174
  listboxId,
167
175
  }: UseComboboxOptions): UseComboboxResult {
168
176
  const [highlightedIndex, setHighlightedIndex] = useState<number>(-1);
@@ -310,6 +318,19 @@ export function useCombobox({
310
318
  }
311
319
  break;
312
320
 
321
+ case 'Delete':
322
+ case 'Backspace':
323
+ // Keyboard equivalent of the clear button (comboboxes-2): clear the
324
+ // value from the closed trigger so clearing is not mouse-only. When
325
+ // hasSearch is active these keys must edit the search text instead,
326
+ // and when the popup is open arrow navigation owns interaction, so
327
+ // only handle the closed non-search case with a clearable value.
328
+ if (!hasSearch && !isOpen && onClear != null && value != null) {
329
+ e.preventDefault();
330
+ onClear();
331
+ }
332
+ break;
333
+
313
334
  default:
314
335
  if (!hasSearch && e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
315
336
  const newTypeahead = typeahead + e.key.toLowerCase();
@@ -349,6 +370,8 @@ export function useCombobox({
349
370
  getEnabledIndices,
350
371
  typeahead,
351
372
  hasSearch,
373
+ onClear,
374
+ value,
352
375
  ],
353
376
  );
354
377
 
@@ -577,6 +577,22 @@ describe('SideNavItem', () => {
577
577
  expect(link).toHaveAttribute('aria-current', 'page');
578
578
  });
579
579
 
580
+ it('places aria-current on the link, not the wrapper, for split-action items', () => {
581
+ // A collapsible item (has children) WITH a primary href renders the
582
+ // split-action path: the link and the expand toggle are siblings inside a
583
+ // wrapper div. aria-current="page" must sit on the focusable link so it is
584
+ // announced as the current page (navigation-8).
585
+ render(
586
+ <SideNavItem label="Reports" href="/reports" isSelected>
587
+ <SideNavItem label="Weekly" href="/reports/weekly" />
588
+ </SideNavItem>,
589
+ );
590
+ const link = screen.getByRole('link', {name: /Reports/});
591
+ expect(link).toHaveAttribute('aria-current', 'page');
592
+ // The wrapper div must NOT carry aria-current.
593
+ expect(link.closest('[aria-current="page"]')).toBe(link);
594
+ });
595
+
580
596
  it('renders custom component when as and href are provided', () => {
581
597
  render(<SideNavItem label="Dashboard" href="/dashboard" as={CustomLink} />);
582
598
  const link = screen.getByRole('link');
@@ -612,16 +612,14 @@ export function SideNavItem({
612
612
 
613
613
  if (hasIndependentToggle) {
614
614
  itemElement = (
615
- <div
616
- aria-current={isSelected ? ('page' as const) : undefined}
617
- data-testid={testId}
618
- {...navItemStyleProps}>
615
+ <div data-testid={testId} {...navItemStyleProps}>
619
616
  <NavItemElement
620
617
  ref={ref}
621
618
  href={href}
622
619
  as={as}
623
620
  isDisabled={isDisabled}
624
621
  onClick={handleClick}
622
+ aria-current={isSelected ? ('page' as const) : undefined}
625
623
  {...stylex.props(styles.splitAction)}>
626
624
  {itemContent}
627
625
  </NavItemElement>
@@ -33,7 +33,17 @@ export const docs = {
33
33
  'Index for staggered animation timing. For element at index n, animation starts at DELAY_TIME + (STAGGER_TIME × n).',
34
34
  default: '0',
35
35
  },
36
- ], theming: {
36
+ ],
37
+ playground: {
38
+ // Skeleton width/height default to '100%', which collapses to a zero-size
39
+ // (invisible) element in the properties-tab preview. Give the example
40
+ // explicit pixel dimensions so the shimmer placeholder is visible.
41
+ defaults: {
42
+ width: 320,
43
+ height: 80,
44
+ },
45
+ },
46
+ theming: {
37
47
  targets: [
38
48
  {className: 'astryx-skeleton'},
39
49
  ],
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {describe, it, expect} from 'vitest';
4
+ import {render, screen} from '@testing-library/react';
5
+ import {Skeleton} from './Skeleton';
6
+
7
+ describe('Skeleton', () => {
8
+ it('renders a placeholder element', () => {
9
+ render(<Skeleton width={200} height={20} data-testid="sk" />);
10
+ expect(screen.getByTestId('sk')).toBeInTheDocument();
11
+ });
12
+
13
+ it('is hidden from assistive tech by default (complex-20)', () => {
14
+ render(<Skeleton width={200} height={20} data-testid="sk" />);
15
+ expect(screen.getByTestId('sk')).toHaveAttribute('aria-hidden', 'true');
16
+ });
17
+
18
+ it('allows the aria-hidden default to be overridden', () => {
19
+ render(
20
+ <Skeleton width={200} height={20} data-testid="sk" aria-hidden={false} />,
21
+ );
22
+ // Consumer opt-out: not hidden when explicitly set false.
23
+ expect(screen.getByTestId('sk')).toHaveAttribute('aria-hidden', 'false');
24
+ });
25
+ });
@@ -62,7 +62,12 @@ const styles = stylex.create({
62
62
  animationDirection: 'alternate',
63
63
  animationDuration: durationVars['--duration-medium-max'],
64
64
  animationIterationCount: 'infinite',
65
- animationName: skeletonFade,
65
+ // Disable the pulse under reduced-motion; the static placeholder still
66
+ // reads as loading (complex-20).
67
+ animationName: {
68
+ default: skeletonFade,
69
+ '@media (prefers-reduced-motion: reduce)': 'none',
70
+ },
66
71
  animationTimingFunction: 'steps(10, end)',
67
72
  },
68
73
  });
@@ -180,6 +185,11 @@ export function Skeleton({
180
185
  return (
181
186
  <div
182
187
  ref={ref}
188
+ // Purely decorative loading placeholder — hide from assistive tech so it
189
+ // isn't announced as empty content. The surrounding region should convey
190
+ // the loading/busy state (e.g. aria-busy) (complex-20). Consumers can
191
+ // override via props if a specific skeleton must be exposed.
192
+ aria-hidden="true"
183
193
  data-testid={testId}
184
194
  {...mergeProps(
185
195
  themeProps('skeleton'),
@@ -11,6 +11,10 @@ export const docs = {
11
11
  defaults: {
12
12
  label: 'Volume',
13
13
  value: 50,
14
+ // Give the properties-tab preview a defined width so the track has room
15
+ // to render and stays draggable/interactive (the slider track grows to
16
+ // fill its container, which can collapse without an explicit width).
17
+ width: 300,
14
18
  },
15
19
  },
16
20
  props: [
@@ -91,6 +95,12 @@ export const docs = {
91
95
  description: 'Whether the slider is disabled.',
92
96
  default: 'false',
93
97
  },
98
+ {
99
+ name: 'disabledMessage',
100
+ type: 'string',
101
+ description:
102
+ 'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
103
+ },
94
104
  {
95
105
  name: 'isOptional',
96
106
  type: 'boolean',
@@ -147,6 +157,7 @@ export const docs = {
147
157
  {guidance: true, description: 'Format values with meaningful units like "$50" or "75%" instead of raw numbers.'},
148
158
  {guidance: false, description: 'Use for precise numeric entry; pair with a text input or use NumberInput instead.'},
149
159
  {guidance: false, description: 'Set a step size so large that only a few positions are possible; use SegmentedControl or radio buttons instead.'},
160
+ {guidance: false, description: 'Wrap a disabled slider in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
150
161
  ],
151
162
  },
152
163
  };
@@ -233,6 +244,12 @@ export const docsZh = {
233
244
  description: '是否禁用滑块。',
234
245
  default: 'false',
235
246
  },
247
+ {
248
+ name: 'disabledMessage',
249
+ type: 'string',
250
+ description:
251
+ 'Explains why the slider is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the thumb focusable via aria-disabled (value changes stay blocked). Use this instead of wrapping a disabled Slider in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
252
+ },
236
253
  {
237
254
  name: 'isOptional',
238
255
  type: 'boolean',
@@ -289,6 +306,7 @@ export const docsZh = {
289
306
  {guidance: true, description: 'Format values with meaningful units like "$50" or "75%" instead of raw numbers.'},
290
307
  {guidance: false, description: 'Use for precise numeric entry; pair with a text input or use NumberInput instead.'},
291
308
  {guidance: false, description: 'Set a step size so large that only a few positions are possible; use SegmentedControl or radio buttons instead.'},
309
+ {guidance: false, description: 'Wrap a disabled slider in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
292
310
  ],
293
311
  },
294
312
  };
@@ -303,6 +321,7 @@ export const docsDense = {
303
321
  {guidance: true, description: 'Format values with meaningful units like "$50" or "75%" instead of raw numbers.'},
304
322
  {guidance: false, description: 'Use for precise numeric entry; pair with a text input or use NumberInput instead.'},
305
323
  {guidance: false, description: 'Set a step size so large that only a few positions are possible; use SegmentedControl or radio buttons instead.'},
324
+ {guidance: false, description: 'Wrap a disabled slider in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
306
325
  ],
307
326
  },
308
327
  propDescriptions: {