@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,19 +4,24 @@
4
4
 
5
5
  /**
6
6
  * @file InputGroupContext.ts
7
- * @input None (pure context definition)
7
+ * @input React createContext/use
8
8
  * @output Exports InputGroup context and useInputGroup hook
9
- * @position Shared context; consumed by input components for group-aware styling
9
+ * @position Shared context; consumed by input components for group-aware styling and ARIA associations
10
10
  */
11
11
 
12
12
  import {createContext, use} from 'react';
13
13
 
14
14
  export interface InputGroupContextValue {
15
15
  isInGroup: true;
16
+ /** ID of the group label element, for aria-labelledby composition. */
17
+ labelID: string;
18
+ /** IDs of helper/status text owned by the group, for aria-describedby composition. */
19
+ describedByIDs?: string;
16
20
  }
17
21
 
18
- export const InputGroupContext =
19
- createContext<InputGroupContextValue | null>(null);
22
+ export const InputGroupContext = createContext<InputGroupContextValue | null>(
23
+ null,
24
+ );
20
25
  InputGroupContext.displayName = 'InputGroupContext';
21
26
 
22
27
  /**
@@ -16,3 +16,4 @@ export {InputGroupText} from './InputGroupText';
16
16
  export type {InputGroupTextProps} from './InputGroupText';
17
17
 
18
18
  export {useInputGroup} from './InputGroupContext';
19
+ export type {InputGroupContextValue} from './InputGroupContext';
@@ -72,10 +72,28 @@ describe('Kbd', () => {
72
72
  expect(screen.getByText('Esc')).toBeInTheDocument();
73
73
  });
74
74
 
75
- it('is aria-hidden', () => {
76
- const {container} = render(<Kbd keys="mod+k" />);
77
- const wrapper = container.firstChild as HTMLElement;
78
- expect(wrapper.getAttribute('aria-hidden')).toBe('true');
75
+ it('exposes a spoken accessible name and hides the glyphs (obs-1)', () => {
76
+ render(<Kbd keys="mod+shift+k" />);
77
+ // The wrapper carries a screen-reader name built from spoken key labels
78
+ // (jsdom is non-Mac, so mod → "Control").
79
+ const img = screen.getByRole('img');
80
+ expect(img).toHaveAttribute('aria-label', 'Control + Shift + K');
81
+ // The visual glyph elements are hidden from assistive tech.
82
+ const glyphs = img.querySelectorAll('kbd');
83
+ glyphs.forEach(g => expect(g).toHaveAttribute('aria-hidden', 'true'));
84
+ expect(img).not.toHaveAttribute('aria-hidden');
85
+ });
86
+
87
+ it('uses "Command" in the accessible name for mod on Mac', () => {
88
+ Object.defineProperty(navigator, 'platform', {
89
+ value: 'MacIntel',
90
+ configurable: true,
91
+ });
92
+ render(<Kbd keys="mod+k" />);
93
+ expect(screen.getByRole('img')).toHaveAttribute(
94
+ 'aria-label',
95
+ 'Command + K',
96
+ );
79
97
  });
80
98
 
81
99
  it('uppercases unknown keys', () => {
package/src/Kbd/Kbd.tsx CHANGED
@@ -45,7 +45,7 @@ const styles = stylex.create({
45
45
  backgroundColor: colorVars['--color-neutral'],
46
46
  borderBottomWidth: '2px',
47
47
  borderBottomStyle: 'solid',
48
- borderBottomColor: colorVars['--color-border'],
48
+ borderBottomColor: colorVars['--color-border-emphasized'],
49
49
  color: colorVars['--color-text-secondary'],
50
50
  fontFamily: typographyVars['--font-family-body'],
51
51
  fontSize: typeScaleVars['--text-supporting-size'],
@@ -87,6 +87,33 @@ function getKeyDisplay(key: string, isMac: boolean): string {
87
87
  return KEY_DISPLAY[key] ?? key.toUpperCase();
88
88
  }
89
89
 
90
+ /**
91
+ * Spoken-word labels for screen readers. The visual `KEY_DISPLAY` uses glyphs
92
+ * (⌘, ⇧, ↵, …) that assistive tech cannot announce meaningfully, so the
93
+ * accessible name for the shortcut is built from these words instead.
94
+ */
95
+ const KEY_LABEL: Record<string, string> = {
96
+ ctrl: 'Control',
97
+ alt: 'Alt',
98
+ shift: 'Shift',
99
+ enter: 'Enter',
100
+ backspace: 'Backspace',
101
+ escape: 'Escape',
102
+ tab: 'Tab',
103
+ up: 'Up arrow',
104
+ down: 'Down arrow',
105
+ left: 'Left arrow',
106
+ right: 'Right arrow',
107
+ plus: 'Plus',
108
+ };
109
+
110
+ function getKeyLabel(key: string, isMac: boolean): string {
111
+ if (key === 'mod') {
112
+ return isMac ? 'Command' : 'Control';
113
+ }
114
+ return KEY_LABEL[key] ?? key.toUpperCase();
115
+ }
116
+
90
117
  function subscribeToPlatformChanges(): () => void {
91
118
  return () => {};
92
119
  }
@@ -146,14 +173,7 @@ export interface KbdProps extends BaseProps<HTMLSpanElement> {
146
173
  * <Kbd keys="mod+k" />
147
174
  * ```
148
175
  */
149
- export function Kbd({
150
- keys,
151
- ref,
152
- xstyle,
153
- className,
154
- style,
155
- ...rest
156
- }: KbdProps) {
176
+ export function Kbd({keys, ref, xstyle, className, style, ...rest}: KbdProps) {
157
177
  const isMac = useSyncExternalStore(
158
178
  subscribeToPlatformChanges,
159
179
  detectMac,
@@ -162,19 +182,24 @@ export function Kbd({
162
182
 
163
183
  const parts = keys.split('+').map(key => key.trim().toLowerCase());
164
184
 
185
+ // Screen-reader name: the joined spoken labels (e.g. "Command + K"), since
186
+ // the visual glyphs below are announced meaninglessly by assistive tech.
187
+ const accessibleName = parts.map(key => getKeyLabel(key, isMac)).join(' + ');
188
+
165
189
  return (
166
190
  <span
167
191
  ref={ref}
192
+ role="img"
193
+ aria-label={accessibleName}
168
194
  {...rest}
169
195
  {...mergeProps(
170
196
  themeProps('kbd'),
171
197
  stylex.props(styles.wrapper, xstyle),
172
198
  className,
173
199
  style,
174
- )}
175
- aria-hidden="true">
200
+ )}>
176
201
  {parts.map(key => (
177
- <kbd key={key} {...stylex.props(styles.kbd)}>
202
+ <kbd key={key} aria-hidden="true" {...stylex.props(styles.kbd)}>
178
203
  {getKeyDisplay(key, isMac)}
179
204
  </kbd>
180
205
  ))}
@@ -0,0 +1,146 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file anchorName.test.ts
5
+ * @input Uses vitest, anchorName utilities
6
+ * @output Unit tests for anchor-name list manipulation helpers
7
+ * @position Testing; validates anchorName.ts implementation
8
+ *
9
+ * SYNC: When anchorName.ts changes, update tests to match new behavior
10
+ */
11
+
12
+ import {describe, it, expect} from 'vitest';
13
+ import {
14
+ readAnchorNames,
15
+ writeAnchorNames,
16
+ addAnchorName,
17
+ removeAnchorName,
18
+ } from './anchorName';
19
+
20
+ function createMockElement(): HTMLElement {
21
+ const el = document.createElement('div');
22
+ return el;
23
+ }
24
+
25
+ describe('readAnchorNames', () => {
26
+ it('returns empty array for element with no anchor-name', () => {
27
+ const el = createMockElement();
28
+ expect(readAnchorNames(el)).toEqual([]);
29
+ });
30
+
31
+ it('reads a single anchor name', () => {
32
+ const el = createMockElement();
33
+ (el.style as unknown as Record<string, string>).anchorName = '--layer-1';
34
+ expect(readAnchorNames(el)).toEqual(['--layer-1']);
35
+ });
36
+
37
+ it('reads multiple comma-separated anchor names', () => {
38
+ const el = createMockElement();
39
+ (el.style as unknown as Record<string, string>).anchorName =
40
+ '--layer-1, --layer-2, --layer-3';
41
+ expect(readAnchorNames(el)).toEqual([
42
+ '--layer-1',
43
+ '--layer-2',
44
+ '--layer-3',
45
+ ]);
46
+ });
47
+
48
+ it('trims whitespace around names', () => {
49
+ const el = createMockElement();
50
+ (el.style as unknown as Record<string, string>).anchorName =
51
+ ' --layer-1 , --layer-2 ';
52
+ expect(readAnchorNames(el)).toEqual(['--layer-1', '--layer-2']);
53
+ });
54
+
55
+ it('returns empty array for empty string value', () => {
56
+ const el = createMockElement();
57
+ (el.style as unknown as Record<string, string>).anchorName = '';
58
+ expect(readAnchorNames(el)).toEqual([]);
59
+ });
60
+ });
61
+
62
+ describe('writeAnchorNames', () => {
63
+ it('writes names as comma-separated list', () => {
64
+ const el = createMockElement();
65
+ writeAnchorNames(el, ['--layer-1', '--layer-2']);
66
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe(
67
+ '--layer-1, --layer-2',
68
+ );
69
+ });
70
+
71
+ it('writes empty string for empty array', () => {
72
+ const el = createMockElement();
73
+ writeAnchorNames(el, []);
74
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe('');
75
+ });
76
+ });
77
+
78
+ describe('addAnchorName', () => {
79
+ it('adds name to element with no existing anchors', () => {
80
+ const el = createMockElement();
81
+ addAnchorName(el, '--layer-1');
82
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe(
83
+ '--layer-1',
84
+ );
85
+ });
86
+
87
+ it('appends name to existing anchor list', () => {
88
+ const el = createMockElement();
89
+ (el.style as unknown as Record<string, string>).anchorName = '--layer-1';
90
+ addAnchorName(el, '--layer-2');
91
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe(
92
+ '--layer-1, --layer-2',
93
+ );
94
+ });
95
+
96
+ it('does not duplicate an already-present name', () => {
97
+ const el = createMockElement();
98
+ (el.style as unknown as Record<string, string>).anchorName = '--layer-1';
99
+ addAnchorName(el, '--layer-1');
100
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe(
101
+ '--layer-1',
102
+ );
103
+ });
104
+
105
+ it('supports multiple layers sharing one element', () => {
106
+ const el = createMockElement();
107
+ addAnchorName(el, '--menu-1');
108
+ addAnchorName(el, '--menu-2');
109
+ addAnchorName(el, '--menu-3');
110
+ expect(readAnchorNames(el)).toEqual(['--menu-1', '--menu-2', '--menu-3']);
111
+ });
112
+ });
113
+
114
+ describe('removeAnchorName', () => {
115
+ it('removes name from a multi-anchor list', () => {
116
+ const el = createMockElement();
117
+ (el.style as unknown as Record<string, string>).anchorName =
118
+ '--layer-1, --layer-2, --layer-3';
119
+ removeAnchorName(el, '--layer-2');
120
+ expect(readAnchorNames(el)).toEqual(['--layer-1', '--layer-3']);
121
+ });
122
+
123
+ it('removes the last remaining name, leaving empty string', () => {
124
+ const el = createMockElement();
125
+ (el.style as unknown as Record<string, string>).anchorName = '--layer-1';
126
+ removeAnchorName(el, '--layer-1');
127
+ expect((el.style as unknown as Record<string, string>).anchorName).toBe('');
128
+ });
129
+
130
+ it('is a no-op if name is not present', () => {
131
+ const el = createMockElement();
132
+ (el.style as unknown as Record<string, string>).anchorName =
133
+ '--layer-1, --layer-2';
134
+ removeAnchorName(el, '--layer-3');
135
+ expect(readAnchorNames(el)).toEqual(['--layer-1', '--layer-2']);
136
+ });
137
+
138
+ it('handles multiple add/remove cycles correctly', () => {
139
+ const el = createMockElement();
140
+ addAnchorName(el, '--menu-a');
141
+ addAnchorName(el, '--menu-b');
142
+ removeAnchorName(el, '--menu-a');
143
+ addAnchorName(el, '--menu-c');
144
+ expect(readAnchorNames(el)).toEqual(['--menu-b', '--menu-c']);
145
+ });
146
+ });
@@ -0,0 +1,46 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file anchorName.ts
5
+ * @input HTMLElement with CSS anchor-name property
6
+ * @output Helpers for managing comma-separated anchor-name lists
7
+ * @position Utility; used by useLayer for multi-anchor support
8
+ *
9
+ * SYNC: When modified, update:
10
+ * - /packages/core/src/Layer/useLayer.tsx (imports from here)
11
+ */
12
+
13
+ /**
14
+ * CSS `anchor-name` is a comma-separated list, so multiple layers can anchor to
15
+ * the same element (e.g. several TopNavMegaMenus anchored to one <nav>). These
16
+ * helpers add/remove a single layer's anchor id without clobbering the others —
17
+ * overwriting the whole property would break every sibling layer's positioning.
18
+ */
19
+
20
+ export function readAnchorNames(el: HTMLElement): string[] {
21
+ const value =
22
+ (el.style as unknown as Record<string, string>).anchorName ?? '';
23
+ return value
24
+ .split(',')
25
+ .map(name => name.trim())
26
+ .filter(Boolean);
27
+ }
28
+
29
+ export function writeAnchorNames(el: HTMLElement, names: string[]): void {
30
+ (el.style as unknown as Record<string, string>).anchorName = names.join(', ');
31
+ }
32
+
33
+ export function addAnchorName(el: HTMLElement, name: string): void {
34
+ const names = readAnchorNames(el);
35
+ if (!names.includes(name)) {
36
+ names.push(name);
37
+ writeAnchorNames(el, names);
38
+ }
39
+ }
40
+
41
+ export function removeAnchorName(el: HTMLElement, name: string): void {
42
+ writeAnchorNames(
43
+ el,
44
+ readAnchorNames(el).filter(existing => existing !== name),
45
+ );
46
+ }
@@ -72,22 +72,38 @@ const animationBase = {
72
72
  *
73
73
  * Keyed by LayerPlacement ('above' | 'below' | 'start' | 'end')
74
74
  * for easy lookup: `layerAnimations[placement]`.
75
+ *
76
+ * Each entry disables its keyframe animation under
77
+ * `prefers-reduced-motion: reduce` so the layer appears instantly instead of
78
+ * translating/scaling in (infra-6).
75
79
  */
76
80
  export const layerAnimations = stylex.create({
77
81
  below: {
78
- animationName: enterBelow,
82
+ animationName: {
83
+ default: enterBelow,
84
+ '@media (prefers-reduced-motion: reduce)': 'none',
85
+ },
79
86
  ...animationBase,
80
87
  },
81
88
  above: {
82
- animationName: enterAbove,
89
+ animationName: {
90
+ default: enterAbove,
91
+ '@media (prefers-reduced-motion: reduce)': 'none',
92
+ },
83
93
  ...animationBase,
84
94
  },
85
95
  end: {
86
- animationName: enterEnd,
96
+ animationName: {
97
+ default: enterEnd,
98
+ '@media (prefers-reduced-motion: reduce)': 'none',
99
+ },
87
100
  ...animationBase,
88
101
  },
89
102
  start: {
90
- animationName: enterStart,
103
+ animationName: {
104
+ default: enterStart,
105
+ '@media (prefers-reduced-motion: reduce)': 'none',
106
+ },
91
107
  ...animationBase,
92
108
  },
93
109
  });
@@ -78,7 +78,7 @@ export const docs = {
78
78
  name: 'render',
79
79
  type: '(children: ReactNode, props: ContextRenderProps | FixedRenderProps) => ReactNode',
80
80
  description:
81
- 'Render function for the popover element. Pass placement/alignment in context mode or x/y in fixed mode.',
81
+ 'Render function for the popover element. Pass placement/alignment in context mode or x/y in fixed mode. In context mode, pass `as: "span"` to render an inline-safe layer (e.g. inside a paragraph). The layer renders inline in the React tree; the Popover API promotes it to the top layer when shown, so it escapes ancestor clipping and stacking without a portal.',
82
82
  },
83
83
  ],
84
84
  usage: {
@@ -95,6 +95,11 @@ export const docs = {
95
95
  description:
96
96
  'Build on higher-level components like Popover, HoverCard, and Tooltip for common overlay patterns.',
97
97
  },
98
+ {
99
+ guidance: true,
100
+ description:
101
+ 'Rely on the Popover API top layer to escape ancestor clipping and stacking: render the layer inline (no portal) so it inherits the trigger\'s theme cascade and keeps a natural focus order. Use `as: "span"` when the layer must be valid inside inline contexts like a paragraph.',
102
+ },
98
103
  {
99
104
  guidance: false,
100
105
  description:
@@ -125,7 +130,7 @@ export const docsDense = {
125
130
  hide: 'hide layer.',
126
131
  isOpen: 'whether layer is open.',
127
132
  id: 'unique ARIA id.',
128
- render: 'renders popover element; pass placement/alignment or x/y.',
133
+ render: 'renders popover element; pass placement/alignment or x/y. Context mode accepts `as: "span"` for inline-safe layers. Renders inline; the Popover API top layer escapes clipping/stacking without a portal.',
129
134
  },
130
135
  usage: {
131
136
  description:
@@ -139,6 +144,11 @@ export const docsDense = {
139
144
  guidance: true,
140
145
  description: 'Build on Popover/HoverCard/Tooltip for common overlay patterns.',
141
146
  },
147
+ {
148
+ guidance: true,
149
+ description:
150
+ 'Rely on the Popover API top layer to escape clipping/stacking: render inline (no portal) to inherit the trigger theme cascade and natural focus order. Use `as: "span"` when the layer must be valid in inline contexts like a paragraph.',
151
+ },
142
152
  {
143
153
  guidance: false,
144
154
  description:
@@ -15,6 +15,7 @@
15
15
 
16
16
  import React, {
17
17
  useCallback,
18
+ useEffect,
18
19
  useId,
19
20
  useRef,
20
21
  useState,
@@ -23,6 +24,7 @@ import React, {
23
24
  } from 'react';
24
25
  import * as stylex from '@stylexjs/stylex';
25
26
  import type {StyleXStyles} from '@stylexjs/stylex';
27
+ import {addAnchorName, removeAnchorName} from './anchorName';
26
28
  import {typographyVars} from '../theme/tokens.stylex';
27
29
 
28
30
  const styles = stylex.create({
@@ -65,6 +67,12 @@ export type LayerAlignment = 'start' | 'center' | 'end';
65
67
  export interface ContextRenderProps {
66
68
  placement?: LayerPlacement;
67
69
  alignment?: LayerAlignment;
70
+ /**
71
+ * ARIA role applied to the popover container (e.g. `'tooltip'`). Lets
72
+ * consumers complete the ARIA pattern and gives test tooling a stable,
73
+ * non-hashed selector for the layer.
74
+ */
75
+ role?: string;
68
76
  /**
69
77
  * StyleX styles for the popover container.
70
78
  */
@@ -79,6 +87,29 @@ export interface ContextRenderProps {
79
87
  * Merged after StyleX and anchor positioning styles.
80
88
  */
81
89
  style?: React.CSSProperties;
90
+ /**
91
+ * HTML tag to render the popover container as.
92
+ *
93
+ * Defaults to `'div'`. Pass `'span'` when the layer must render inline-safe
94
+ * markup — e.g. a `HoverCard` wrapping inline text inside a `<p>`. A `<span>`
95
+ * is phrasing content, so it stays put in the DOM tree instead of being
96
+ * reparented out of a paragraph by the HTML parser, which keeps server and
97
+ * client markup identical. The Popover API and CSS anchor positioning work
98
+ * the same on either tag.
99
+ *
100
+ * @default 'div'
101
+ */
102
+ as?: 'div' | 'span';
103
+ /**
104
+ * Pointer-enter handler attached to the popover container itself. Lets a
105
+ * consumer keep a hover-driven layer open while the pointer is over the
106
+ * surface (e.g. Tooltip/HoverCard "hoverable" behavior — WCAG 1.4.13).
107
+ */
108
+ onMouseEnter?: React.MouseEventHandler<HTMLElement>;
109
+ /**
110
+ * Pointer-leave handler attached to the popover container itself.
111
+ */
112
+ onMouseLeave?: React.MouseEventHandler<HTMLElement>;
82
113
  }
83
114
 
84
115
  /**
@@ -311,16 +342,14 @@ export function useLayer(
311
342
  const ref: RefCallback<HTMLElement> | undefined =
312
343
  mode === 'context'
313
344
  ? (el: HTMLElement | null) => {
314
- // Cleanup previous element
315
- if (triggerRef.current) {
316
- (
317
- triggerRef.current.style as unknown as Record<string, string>
318
- ).anchorName = '';
345
+ // Remove only THIS layer's anchor name from the previous element so
346
+ // other layers sharing the same trigger keep their anchors.
347
+ if (triggerRef.current && triggerRef.current !== el) {
348
+ removeAnchorName(triggerRef.current, anchorId);
319
349
  }
320
350
 
321
351
  if (el) {
322
- (el.style as unknown as Record<string, string>).anchorName =
323
- anchorId;
352
+ addAnchorName(el, anchorId);
324
353
  }
325
354
 
326
355
  triggerRef.current = el;
@@ -349,26 +378,76 @@ export function useLayer(
349
378
  [onHide],
350
379
  );
351
380
 
352
- // Ref callback for popover element — sets up toggle listener
381
+ // Ref callback for popover element — sets up the `toggle` listener.
382
+ // Tracks the element + handler currently bound so the listener is removed
383
+ // when the element detaches or when `handleToggle`'s identity changes (a new
384
+ // `onHide` prop), preventing stale-closure listeners from accumulating on the
385
+ // same element (infra-10).
386
+ const listenedElRef = useRef<HTMLElement | null>(null);
387
+ const listenedHandlerRef = useRef<((e: Event) => void) | null>(null);
388
+
389
+ const bindToggleListener = useCallback(
390
+ (el: HTMLElement | null, handler: (e: Event) => void) => {
391
+ if (
392
+ listenedElRef.current &&
393
+ listenedHandlerRef.current &&
394
+ (listenedElRef.current !== el || listenedHandlerRef.current !== handler)
395
+ ) {
396
+ listenedElRef.current.removeEventListener(
397
+ 'toggle',
398
+ listenedHandlerRef.current,
399
+ );
400
+ listenedElRef.current = null;
401
+ listenedHandlerRef.current = null;
402
+ }
403
+ if (el && listenedElRef.current !== el) {
404
+ el.addEventListener('toggle', handler);
405
+ listenedElRef.current = el;
406
+ listenedHandlerRef.current = handler;
407
+ }
408
+ },
409
+ [],
410
+ );
411
+
353
412
  const popoverRefCallback = useCallback(
354
413
  (el: HTMLElement | null) => {
355
414
  popoverRef.current = el;
356
- if (el) {
357
- el.addEventListener('toggle', handleToggle);
358
- }
415
+ bindToggleListener(el, handleToggle);
359
416
  },
360
- [handleToggle],
417
+ [handleToggle, bindToggleListener],
361
418
  );
362
419
 
420
+ // Re-bind when the handler identity changes while the element stays mounted,
421
+ // and detach on unmount.
422
+ useEffect(() => {
423
+ if (popoverRef.current) {
424
+ bindToggleListener(popoverRef.current, handleToggle);
425
+ }
426
+ return () => {
427
+ if (listenedElRef.current && listenedHandlerRef.current) {
428
+ listenedElRef.current.removeEventListener(
429
+ 'toggle',
430
+ listenedHandlerRef.current,
431
+ );
432
+ listenedElRef.current = null;
433
+ listenedHandlerRef.current = null;
434
+ }
435
+ };
436
+ }, [handleToggle, bindToggleListener]);
437
+
363
438
  // Render function for context mode
364
439
  const renderContext = useCallback(
365
440
  (children: ReactNode, props?: ContextRenderProps) => {
366
441
  const {
367
442
  placement = 'above',
368
443
  alignment = 'center',
444
+ role,
369
445
  xstyle,
370
446
  className: extraClassName,
371
447
  style: extraStyle,
448
+ as: Container = 'div',
449
+ onMouseEnter,
450
+ onMouseLeave,
372
451
  } = props || {};
373
452
 
374
453
  // CSS anchor positioning (dynamic, not in StyleX)
@@ -383,15 +462,21 @@ export function useLayer(
383
462
  ? `${extraClassName} ${stylexResult.className ?? ''}`
384
463
  : stylexResult.className;
385
464
 
465
+ // Render as the requested tag. A `span` keeps the layer phrasing content
466
+ // so it is valid (and stays put on hydration) inside inline contexts like
467
+ // a `<p>`; `div` remains the default for block layers.
386
468
  return (
387
- <div
469
+ <Container
388
470
  ref={popoverRefCallback}
389
471
  id={id}
472
+ role={role}
390
473
  popover={lightDismiss ? 'auto' : 'manual'}
391
474
  className={combinedClassName}
392
- style={{...stylexResult.style, ...anchorStyle, ...extraStyle}}>
475
+ style={{...stylexResult.style, ...anchorStyle, ...extraStyle}}
476
+ onMouseEnter={onMouseEnter}
477
+ onMouseLeave={onMouseLeave}>
393
478
  {children}
394
- </div>
479
+ </Container>
395
480
  );
396
481
  },
397
482
  [anchorId, id, lightDismiss, popoverRefCallback],
@@ -30,7 +30,7 @@ export const docs = {
30
30
  name: 'content',
31
31
  type: 'ReactNode',
32
32
  description:
33
- 'Main content area (center). Children passed to `<Layout>` render here too — `<Layout>{main}</Layout>` is shorthand for `<Layout content={main} />`.',
33
+ 'Main content area (center). Children passed to `<Layout>` render here too: `<Layout>{main}</Layout>` is shorthand for `<Layout content={main} />`.',
34
34
  slotElements: [
35
35
  {
36
36
  __element: 'LayoutContent',