@astryxdesign/core 0.1.3 → 0.1.4-canary.01e5b29

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 (642) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +20 -18
  5. package/dist/AlertDialog/useImperativeAlertDialog.js +3 -3
  6. package/dist/AppShell/AppShell.d.ts +1 -1
  7. package/dist/AppShell/AppShell.d.ts.map +1 -1
  8. package/dist/AppShell/AppShell.js +55 -53
  9. package/dist/AspectRatio/AspectRatio.js +5 -5
  10. package/dist/Avatar/Avatar.d.ts.map +1 -1
  11. package/dist/Avatar/Avatar.js +27 -25
  12. package/dist/Avatar/AvatarStatusDot.js +5 -5
  13. package/dist/AvatarGroup/AvatarGroup.js +5 -5
  14. package/dist/AvatarGroup/AvatarGroupOverflow.js +5 -5
  15. package/dist/Badge/Badge.js +3 -3
  16. package/dist/Banner/Banner.d.ts.map +1 -1
  17. package/dist/Banner/Banner.js +32 -25
  18. package/dist/Blockquote/Blockquote.js +7 -7
  19. package/dist/Breadcrumbs/BreadcrumbItem.js +17 -17
  20. package/dist/Breadcrumbs/Breadcrumbs.js +7 -7
  21. package/dist/Button/Button.d.ts.map +1 -1
  22. package/dist/Button/Button.js +47 -26
  23. package/dist/ButtonGroup/ButtonGroup.js +7 -7
  24. package/dist/Calendar/Calendar.d.ts.map +1 -1
  25. package/dist/Calendar/Calendar.js +108 -64
  26. package/dist/Calendar/dayCellUtils.d.ts +67 -5
  27. package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
  28. package/dist/Calendar/dayCellUtils.js +139 -18
  29. package/dist/Calendar/styles.d.ts +2 -2
  30. package/dist/Calendar/styles.d.ts.map +1 -1
  31. package/dist/Calendar/styles.js +2 -2
  32. package/dist/Card/Card.d.ts +4 -2
  33. package/dist/Card/Card.d.ts.map +1 -1
  34. package/dist/Card/Card.js +18 -10
  35. package/dist/Carousel/Carousel.d.ts.map +1 -1
  36. package/dist/Carousel/Carousel.js +20 -19
  37. package/dist/Center/Center.js +3 -3
  38. package/dist/Chat/ChatComposer.js +23 -23
  39. package/dist/Chat/ChatComposerDrawer.js +14 -14
  40. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  41. package/dist/Chat/ChatComposerInput.js +27 -15
  42. package/dist/Chat/ChatDictationButton.d.ts +1 -1
  43. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  44. package/dist/Chat/ChatDictationButton.js +13 -11
  45. package/dist/Chat/ChatLayout.js +17 -17
  46. package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
  47. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  48. package/dist/Chat/ChatLayoutScrollButton.js +12 -10
  49. package/dist/Chat/ChatMessage.js +12 -12
  50. package/dist/Chat/ChatMessageBubble.js +7 -7
  51. package/dist/Chat/ChatMessageList.js +14 -14
  52. package/dist/Chat/ChatMessageMetadata.d.ts +1 -1
  53. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  54. package/dist/Chat/ChatMessageMetadata.js +14 -12
  55. package/dist/Chat/ChatPastedTextToken.js +13 -13
  56. package/dist/Chat/ChatSendButton.js +3 -3
  57. package/dist/Chat/ChatSystemMessage.d.ts +1 -1
  58. package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
  59. package/dist/Chat/ChatSystemMessage.js +17 -17
  60. package/dist/Chat/ChatTokenizedText.d.ts +1 -1
  61. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  62. package/dist/Chat/ChatTokenizedText.js +24 -15
  63. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  64. package/dist/Chat/ChatToolCalls.js +81 -74
  65. package/dist/Chat/index.d.ts +1 -1
  66. package/dist/Chat/index.d.ts.map +1 -1
  67. package/dist/Chat/useTriggerMenu.js +15 -15
  68. package/dist/CheckboxInput/CheckboxInput.d.ts +6 -1
  69. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  70. package/dist/CheckboxInput/CheckboxInput.js +32 -24
  71. package/dist/CheckboxList/CheckboxList.js +9 -9
  72. package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
  73. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  74. package/dist/CheckboxList/CheckboxListItem.js +8 -6
  75. package/dist/Citation/Citation.js +10 -10
  76. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  77. package/dist/ClickableCard/ClickableCard.js +32 -9
  78. package/dist/Code/Code.d.ts +15 -1
  79. package/dist/Code/Code.d.ts.map +1 -1
  80. package/dist/Code/Code.js +35 -5
  81. package/dist/Code/index.d.ts +1 -1
  82. package/dist/Code/index.d.ts.map +1 -1
  83. package/dist/CodeBlock/CodeBlock.d.ts +10 -1
  84. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  85. package/dist/CodeBlock/CodeBlock.js +88 -52
  86. package/dist/CodeBlock/index.d.ts +1 -1
  87. package/dist/CodeBlock/index.d.ts.map +1 -1
  88. package/dist/Collapsible/Collapsible.d.ts +9 -3
  89. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  90. package/dist/Collapsible/Collapsible.js +110 -22
  91. package/dist/Collapsible/CollapsibleGroup.d.ts +39 -7
  92. package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
  93. package/dist/Collapsible/CollapsibleGroup.js +73 -12
  94. package/dist/Collapsible/CollapsibleGroupContext.d.ts +31 -0
  95. package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
  96. package/dist/Collapsible/CollapsibleGroupContext.js +33 -3
  97. package/dist/Collapsible/index.d.ts +1 -0
  98. package/dist/Collapsible/index.d.ts.map +1 -1
  99. package/dist/Collapsible/useCollapsible.d.ts +4 -1
  100. package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
  101. package/dist/Collapsible/useCollapsible.js +20 -6
  102. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  103. package/dist/CommandPalette/CommandPalette.js +36 -34
  104. package/dist/CommandPalette/CommandPaletteEmpty.d.ts +1 -1
  105. package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
  106. package/dist/CommandPalette/CommandPaletteEmpty.js +27 -7
  107. package/dist/CommandPalette/CommandPaletteFooter.js +16 -16
  108. package/dist/CommandPalette/CommandPaletteGroup.js +5 -5
  109. package/dist/CommandPalette/CommandPaletteInput.js +13 -13
  110. package/dist/CommandPalette/CommandPaletteItem.js +3 -3
  111. package/dist/CommandPalette/CommandPaletteList.js +3 -3
  112. package/dist/ContextMenu/ContextMenu.d.ts +9 -1
  113. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  114. package/dist/ContextMenu/ContextMenu.js +16 -11
  115. package/dist/DateInput/DateInput.js +18 -18
  116. package/dist/DateRangeInput/DateRangeInput.js +23 -23
  117. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -7
  118. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  119. package/dist/DateTimeInput/DateTimeInput.js +30 -26
  120. package/dist/DateTimeInput/index.d.ts +1 -1
  121. package/dist/DateTimeInput/index.d.ts.map +1 -1
  122. package/dist/Dialog/Dialog.js +9 -9
  123. package/dist/Dialog/DialogHeader.js +16 -16
  124. package/dist/Dialog/useImperativeDialog.js +3 -3
  125. package/dist/Divider/Divider.d.ts +0 -22
  126. package/dist/Divider/Divider.d.ts.map +1 -1
  127. package/dist/Divider/Divider.js +7 -7
  128. package/dist/DropdownMenu/DropdownMenu.js +10 -10
  129. package/dist/DropdownMenu/DropdownMenuItem.d.ts +2 -17
  130. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  131. package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
  132. package/dist/DropdownMenu/renderDropdownItems.js +10 -10
  133. package/dist/EmptyState/EmptyState.js +9 -9
  134. package/dist/Field/Field.js +17 -17
  135. package/dist/Field/FieldLabel.js +15 -15
  136. package/dist/Field/InputClearButton.js +5 -5
  137. package/dist/FieldStatus/FieldStatus.js +3 -3
  138. package/dist/FileInput/FileInput.js +29 -29
  139. package/dist/FormLayout/FormLayout.js +5 -5
  140. package/dist/Grid/Grid.d.ts +4 -3
  141. package/dist/Grid/Grid.d.ts.map +1 -1
  142. package/dist/Grid/Grid.js +29 -12
  143. package/dist/Grid/GridSpan.js +3 -3
  144. package/dist/HStack/HStack.js +3 -3
  145. package/dist/Heading/Heading.js +10 -10
  146. package/dist/HoverCard/HoverCard.js +9 -9
  147. package/dist/HoverCard/useHoverCard.js +3 -3
  148. package/dist/Icon/Icon.d.ts.map +1 -1
  149. package/dist/Icon/Icon.js +16 -12
  150. package/dist/Icon/defaultIcons.js +116 -116
  151. package/dist/IconButton/IconButton.js +3 -3
  152. package/dist/InputGroup/InputGroup.js +11 -11
  153. package/dist/InputGroup/InputGroupText.js +3 -3
  154. package/dist/Item/Item.js +18 -18
  155. package/dist/Kbd/Kbd.js +5 -5
  156. package/dist/Layer/LayerProvider.js +7 -7
  157. package/dist/Layer/useLayer.js +5 -5
  158. package/dist/Layout/Layout.js +21 -21
  159. package/dist/Layout/LayoutContent.js +3 -3
  160. package/dist/Layout/LayoutFooter.js +5 -5
  161. package/dist/Layout/LayoutHeader.js +5 -5
  162. package/dist/Layout/LayoutPanel.js +3 -3
  163. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  164. package/dist/Lightbox/Lightbox.js +55 -31
  165. package/dist/Lightbox/useLightbox.js +3 -3
  166. package/dist/Link/Link.js +15 -15
  167. package/dist/Link/LinkProvider.js +3 -3
  168. package/dist/Link/useLinkify.js +3 -3
  169. package/dist/List/List.js +11 -11
  170. package/dist/List/ListItem.js +11 -11
  171. package/dist/Markdown/Markdown.d.ts.map +1 -1
  172. package/dist/Markdown/Markdown.js +102 -102
  173. package/dist/Markdown/parser.d.ts +7 -0
  174. package/dist/Markdown/parser.d.ts.map +1 -1
  175. package/dist/Markdown/parser.js +300 -6
  176. package/dist/MetadataList/MetadataList.js +10 -10
  177. package/dist/MetadataList/MetadataListItem.js +15 -15
  178. package/dist/MobileNav/MobileNav.js +15 -15
  179. package/dist/MobileNav/MobileNavToggle.js +5 -5
  180. package/dist/MoreMenu/MoreMenu.js +3 -3
  181. package/dist/MultiSelector/MultiSelector.d.ts +7 -1
  182. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  183. package/dist/MultiSelector/MultiSelector.js +64 -55
  184. package/dist/NavIcon/NavIcon.js +3 -3
  185. package/dist/NavMenu/NavHeadingMenu.js +5 -5
  186. package/dist/NavMenu/NavHeadingMenuItem.js +8 -8
  187. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  188. package/dist/NumberInput/NumberInput.js +48 -32
  189. package/dist/Outline/Outline.js +15 -15
  190. package/dist/OverflowList/OverflowList.js +8 -8
  191. package/dist/Overlay/Overlay.js +3 -3
  192. package/dist/Overlay/OverlayScrim.js +5 -5
  193. package/dist/Overlay/useOverlay.js +3 -3
  194. package/dist/Pagination/Pagination.d.ts +1 -1
  195. package/dist/Pagination/Pagination.d.ts.map +1 -1
  196. package/dist/Pagination/Pagination.js +125 -72
  197. package/dist/Popover/Popover.js +16 -16
  198. package/dist/Popover/usePopover.js +7 -7
  199. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  200. package/dist/PowerSearch/PowerSearch.js +110 -92
  201. package/dist/PowerSearch/PowerSearchEditPopover.js +84 -84
  202. package/dist/PowerSearch/PowerSearchFilterEditor.js +3 -3
  203. package/dist/PowerSearch/PowerSearchToken.js +5 -5
  204. package/dist/PowerSearch/PowerSearchValueEditor.js +54 -54
  205. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  206. package/dist/ProgressBar/ProgressBar.js +25 -18
  207. package/dist/RadioList/RadioList.d.ts +7 -1
  208. package/dist/RadioList/RadioList.d.ts.map +1 -1
  209. package/dist/RadioList/RadioList.js +10 -8
  210. package/dist/RadioList/RadioListItem.d.ts +1 -1
  211. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  212. package/dist/RadioList/RadioListItem.js +30 -22
  213. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  214. package/dist/Resizable/ResizeHandle.js +28 -10
  215. package/dist/Section/Section.js +5 -5
  216. package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
  217. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  218. package/dist/SegmentedControl/SegmentedControl.js +32 -10
  219. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  220. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  221. package/dist/SegmentedControl/SegmentedControlItem.js +18 -12
  222. package/dist/SelectableCard/SelectableCard.js +5 -5
  223. package/dist/Selector/Selector.d.ts +6 -0
  224. package/dist/Selector/Selector.d.ts.map +1 -1
  225. package/dist/Selector/Selector.js +54 -45
  226. package/dist/Selector/SelectorOption.js +3 -3
  227. package/dist/SideNav/SideNav.d.ts.map +1 -1
  228. package/dist/SideNav/SideNav.js +38 -34
  229. package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
  230. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  231. package/dist/SideNav/SideNavCollapseButton.js +8 -6
  232. package/dist/SideNav/SideNavHeading.js +87 -87
  233. package/dist/SideNav/SideNavItem.js +42 -42
  234. package/dist/SideNav/SideNavSection.d.ts +1 -1
  235. package/dist/SideNav/SideNavSection.d.ts.map +1 -1
  236. package/dist/SideNav/SideNavSection.js +18 -16
  237. package/dist/Skeleton/Skeleton.js +3 -3
  238. package/dist/Slider/Slider.d.ts +6 -0
  239. package/dist/Slider/Slider.d.ts.map +1 -1
  240. package/dist/Slider/Slider.js +31 -22
  241. package/dist/Spinner/Spinner.d.ts.map +1 -1
  242. package/dist/Spinner/Spinner.js +10 -10
  243. package/dist/StatusDot/StatusDot.js +5 -5
  244. package/dist/Switch/Switch.d.ts +13 -4
  245. package/dist/Switch/Switch.d.ts.map +1 -1
  246. package/dist/Switch/Switch.js +41 -30
  247. package/dist/TabList/Tab.js +18 -18
  248. package/dist/TabList/TabList.js +5 -5
  249. package/dist/TabList/TabMenu.d.ts.map +1 -1
  250. package/dist/TabList/TabMenu.js +57 -30
  251. package/dist/TabList/tab.markers.stylex.d.ts +1 -1
  252. package/dist/Table/BaseTable.d.ts.map +1 -1
  253. package/dist/Table/BaseTable.js +51 -39
  254. package/dist/Table/Table.js +7 -7
  255. package/dist/Table/TableBody.d.ts +1 -1
  256. package/dist/Table/TableBody.d.ts.map +1 -1
  257. package/dist/Table/TableBody.js +9 -5
  258. package/dist/Table/TableCell.d.ts.map +1 -1
  259. package/dist/Table/TableCell.js +76 -7
  260. package/dist/Table/TableFooter.d.ts +1 -1
  261. package/dist/Table/TableFooter.d.ts.map +1 -1
  262. package/dist/Table/TableFooter.js +9 -5
  263. package/dist/Table/TableHeader.d.ts +1 -1
  264. package/dist/Table/TableHeader.d.ts.map +1 -1
  265. package/dist/Table/TableHeader.js +9 -5
  266. package/dist/Table/TableHeaderCell.js +3 -3
  267. package/dist/Table/TableRow.js +5 -5
  268. package/dist/Table/index.d.ts +2 -0
  269. package/dist/Table/index.d.ts.map +1 -1
  270. package/dist/Table/index.js +1 -0
  271. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  272. package/dist/Table/plugins/columnResize/useTableColumnResize.js +14 -11
  273. package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
  274. package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
  275. package/dist/Table/plugins/pagination/paginateData.js +5 -1
  276. package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
  277. package/dist/Table/plugins/rowExpansion/index.d.ts +3 -0
  278. package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -0
  279. package/dist/Table/plugins/rowExpansion/index.js +3 -0
  280. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +90 -0
  281. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -0
  282. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +398 -0
  283. package/dist/Table/plugins/selection/useTableSelection.js +18 -18
  284. package/dist/Table/plugins/selection/useTableSelectionState.d.ts.map +1 -1
  285. package/dist/Table/plugins/selection/useTableSelectionState.js +11 -1
  286. package/dist/Table/plugins/sortable/useTableSortable.js +17 -17
  287. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  288. package/dist/Table/plugins/sortable/useTableSortableState.js +8 -4
  289. package/dist/Table/tableContextMenu.d.ts +5 -1
  290. package/dist/Table/tableContextMenu.d.ts.map +1 -1
  291. package/dist/Table/tableContextMenu.js +19 -12
  292. package/dist/Text/Text.d.ts +1 -1
  293. package/dist/Text/Text.d.ts.map +1 -1
  294. package/dist/Text/Text.js +14 -13
  295. package/dist/Text/text.stylex.d.ts +35 -0
  296. package/dist/Text/text.stylex.d.ts.map +1 -1
  297. package/dist/Text/text.stylex.js +52 -1
  298. package/dist/TextArea/TextArea.js +14 -14
  299. package/dist/TextInput/TextInput.js +15 -15
  300. package/dist/Thumbnail/Thumbnail.d.ts +3 -2
  301. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  302. package/dist/Thumbnail/Thumbnail.js +30 -29
  303. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  304. package/dist/TimeInput/TimeInput.js +26 -21
  305. package/dist/Timestamp/Timestamp.d.ts +1 -1
  306. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  307. package/dist/Timestamp/Timestamp.js +37 -26
  308. package/dist/Toast/Toast.d.ts.map +1 -1
  309. package/dist/Toast/Toast.js +25 -17
  310. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  311. package/dist/Toast/ToastViewport.js +23 -11
  312. package/dist/Toast/useToast.js +4 -4
  313. package/dist/ToggleButton/ToggleButton.js +12 -12
  314. package/dist/ToggleButton/ToggleButtonGroup.js +5 -5
  315. package/dist/Token/Token.js +21 -21
  316. package/dist/Tokenizer/Tokenizer.d.ts +6 -1
  317. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  318. package/dist/Tokenizer/Tokenizer.js +38 -29
  319. package/dist/Toolbar/Toolbar.js +18 -18
  320. package/dist/Tooltip/Tooltip.js +11 -11
  321. package/dist/Tooltip/useTooltip.js +3 -3
  322. package/dist/TopNav/TopNav.js +32 -32
  323. package/dist/TopNav/TopNavHeading.js +67 -67
  324. package/dist/TopNav/TopNavItem.js +5 -5
  325. package/dist/TopNav/TopNavMegaMenu.js +30 -30
  326. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
  327. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  328. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +25 -14
  329. package/dist/TopNav/TopNavMegaMenuItem.js +16 -16
  330. package/dist/TopNav/TopNavMenu.js +32 -32
  331. package/dist/TreeList/TreeList.js +8 -8
  332. package/dist/TreeList/TreeListBranches.js +11 -11
  333. package/dist/TreeList/TreeListItem.js +30 -30
  334. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  335. package/dist/Typeahead/BaseTypeahead.js +23 -20
  336. package/dist/Typeahead/Typeahead.js +12 -12
  337. package/dist/Typeahead/TypeaheadItem.js +10 -10
  338. package/dist/VStack/VStack.js +3 -3
  339. package/dist/astryx.css +23 -0
  340. package/dist/astryx.umd.js +60 -58
  341. package/dist/astryx.umd.js.map +4 -4
  342. package/dist/docs-types.d.ts +13 -1
  343. package/dist/docs-types.d.ts.map +1 -1
  344. package/dist/hooks/focusableSelector.d.ts +1 -1
  345. package/dist/hooks/focusableSelector.d.ts.map +1 -1
  346. package/dist/hooks/focusableSelector.js +1 -1
  347. package/dist/hooks/index.d.ts +2 -0
  348. package/dist/hooks/index.d.ts.map +1 -1
  349. package/dist/hooks/index.js +1 -0
  350. package/dist/hooks/useFocusTrap.d.ts +3 -0
  351. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  352. package/dist/hooks/useFocusTrap.js +38 -1
  353. package/dist/hooks/useHotkeys.d.ts +51 -0
  354. package/dist/hooks/useHotkeys.d.ts.map +1 -0
  355. package/dist/hooks/useHotkeys.js +160 -0
  356. package/dist/hooks/useInteractiveRole.d.ts +6 -2
  357. package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
  358. package/dist/hooks/useInteractiveRole.js +6 -2
  359. package/dist/hooks/useKeyboardHint.js +9 -9
  360. package/dist/hooks/useStreamingText.d.ts +3 -1
  361. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  362. package/dist/hooks/useStreamingText.js +14 -5
  363. package/dist/theme/MediaTheme.js +3 -3
  364. package/dist/theme/Theme.js +7 -7
  365. package/dist/theme/defineTheme.d.ts +1 -1
  366. package/dist/theme/defineTheme.d.ts.map +1 -1
  367. package/dist/theme/expandColorScale.d.ts.map +1 -1
  368. package/dist/theme/expandColorScale.js +10 -3
  369. package/dist/theme/hct.d.ts +0 -15
  370. package/dist/theme/hct.d.ts.map +1 -1
  371. package/dist/theme/hct.js +9 -9
  372. package/dist/theme/syntax/SyntaxTheme.js +5 -5
  373. package/dist/theme/tokens.d.ts +10 -2
  374. package/dist/theme/tokens.d.ts.map +1 -1
  375. package/dist/theme/tokens.js +220 -4
  376. package/dist/utils/color.d.ts +42 -0
  377. package/dist/utils/color.d.ts.map +1 -0
  378. package/dist/utils/color.js +150 -0
  379. package/dist/utils/composeEventHandlers.d.ts +30 -0
  380. package/dist/utils/composeEventHandlers.d.ts.map +1 -0
  381. package/dist/utils/composeEventHandlers.js +40 -0
  382. package/dist/utils/index.d.ts +3 -0
  383. package/dist/utils/index.d.ts.map +1 -1
  384. package/dist/utils/index.js +3 -1
  385. package/dist/utils/timeParser.d.ts.map +1 -1
  386. package/dist/utils/timeParser.js +8 -5
  387. package/package.json +3 -3
  388. package/src/AlertDialog/AlertDialog.tsx +2 -0
  389. package/src/AppShell/AppShell.tsx +2 -0
  390. package/src/AspectRatio/AspectRatio.doc.mjs +1 -1
  391. package/src/Avatar/Avatar.doc.mjs +13 -2
  392. package/src/Avatar/Avatar.test.tsx +32 -1
  393. package/src/Avatar/Avatar.tsx +12 -20
  394. package/src/Banner/Banner.doc.mjs +8 -0
  395. package/src/Banner/Banner.test.tsx +38 -0
  396. package/src/Banner/Banner.tsx +8 -1
  397. package/src/Button/Button.tsx +39 -6
  398. package/src/ButtonGroup/ButtonGroup.doc.mjs +1 -1
  399. package/src/Calendar/Calendar.doc.mjs +1 -1
  400. package/src/Calendar/Calendar.test.tsx +201 -17
  401. package/src/Calendar/Calendar.tsx +79 -26
  402. package/src/Calendar/dayCellUtils.test.ts +306 -1
  403. package/src/Calendar/dayCellUtils.ts +206 -13
  404. package/src/Calendar/styles.ts +12 -2
  405. package/src/Card/Card.doc.mjs +1 -1
  406. package/src/Card/Card.tsx +16 -6
  407. package/src/Carousel/Carousel.doc.mjs +12 -12
  408. package/src/Carousel/Carousel.test.tsx +13 -0
  409. package/src/Carousel/Carousel.tsx +1 -0
  410. package/src/Chat/Chat.doc.mjs +1 -1
  411. package/src/Chat/ChatComposerInput.test.tsx +24 -0
  412. package/src/Chat/ChatComposerInput.tsx +17 -1
  413. package/src/Chat/ChatDictationButton.test.tsx +43 -0
  414. package/src/Chat/ChatDictationButton.tsx +4 -4
  415. package/src/Chat/ChatLayoutScrollButton.test.tsx +33 -0
  416. package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
  417. package/src/Chat/ChatMessageMetadata.test.tsx +32 -0
  418. package/src/Chat/ChatMessageMetadata.tsx +4 -6
  419. package/src/Chat/ChatSystemMessage.test.tsx +26 -11
  420. package/src/Chat/ChatSystemMessage.tsx +7 -7
  421. package/src/Chat/ChatTokenizedText.test.tsx +29 -16
  422. package/src/Chat/ChatTokenizedText.tsx +15 -8
  423. package/src/Chat/ChatToolCalls.test.tsx +55 -0
  424. package/src/Chat/ChatToolCalls.tsx +10 -12
  425. package/src/Chat/index.ts +1 -4
  426. package/src/Chat/useChatNewMessages.test.tsx +4 -4
  427. package/src/CheckboxInput/CheckboxInput.doc.mjs +12 -4
  428. package/src/CheckboxInput/CheckboxInput.test.tsx +103 -0
  429. package/src/CheckboxInput/CheckboxInput.tsx +13 -0
  430. package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
  431. package/src/CheckboxList/CheckboxList.test.tsx +19 -0
  432. package/src/CheckboxList/CheckboxListItem.tsx +11 -2
  433. package/src/Citation/Citation.doc.mjs +5 -0
  434. package/src/ClickableCard/ClickableCard.tsx +45 -2
  435. package/src/Code/Code.test.tsx +54 -0
  436. package/src/Code/Code.tsx +48 -4
  437. package/src/Code/index.ts +1 -1
  438. package/src/CodeBlock/CodeBlock.doc.mjs +7 -2
  439. package/src/CodeBlock/CodeBlock.test.tsx +122 -3
  440. package/src/CodeBlock/CodeBlock.tsx +62 -4
  441. package/src/CodeBlock/index.ts +1 -1
  442. package/src/Collapsible/Collapsible.doc.mjs +8 -4
  443. package/src/Collapsible/Collapsible.test.tsx +405 -0
  444. package/src/Collapsible/Collapsible.tsx +86 -10
  445. package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
  446. package/src/Collapsible/CollapsibleGroup.test.tsx +318 -0
  447. package/src/Collapsible/CollapsibleGroup.tsx +107 -9
  448. package/src/Collapsible/CollapsibleGroupContext.tsx +42 -2
  449. package/src/Collapsible/index.ts +4 -0
  450. package/src/Collapsible/useCollapsible.ts +20 -6
  451. package/src/CommandPalette/CommandPalette.tsx +5 -3
  452. package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
  453. package/src/CommandPalette/CommandPaletteEmpty.tsx +15 -1
  454. package/src/CommandPalette/CommandPaletteGroup.doc.mjs +10 -0
  455. package/src/CommandPalette/CommandPaletteInput.doc.mjs +6 -0
  456. package/src/CommandPalette/CommandPaletteItem.doc.mjs +6 -0
  457. package/src/CommandPalette/CommandPaletteList.doc.mjs +9 -0
  458. package/src/ContextMenu/ContextMenu.doc.mjs +15 -0
  459. package/src/ContextMenu/ContextMenu.test.tsx +15 -0
  460. package/src/ContextMenu/ContextMenu.tsx +19 -1
  461. package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
  462. package/src/DateInput/DateInput.doc.mjs +6 -1
  463. package/src/DateInput/DateInput.test.tsx +11 -20
  464. package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
  465. package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
  466. package/src/DateRangeInput/DateRangeInput.tsx +2 -2
  467. package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -3
  468. package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
  469. package/src/DateTimeInput/DateTimeInput.tsx +9 -8
  470. package/src/DateTimeInput/index.ts +1 -0
  471. package/src/Dialog/DialogHeader.doc.mjs +45 -0
  472. package/src/Divider/Divider.tsx +1 -23
  473. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
  474. package/src/DropdownMenu/DropdownMenu.test.tsx +5 -3
  475. package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
  476. package/src/EmptyState/EmptyState.doc.mjs +1 -1
  477. package/src/Field/Field.doc.mjs +1 -1
  478. package/src/Field/FieldLabel.test.tsx +2 -2
  479. package/src/FieldStatus/FieldStatus.test.tsx +282 -0
  480. package/src/FileInput/FileInput.doc.mjs +1 -1
  481. package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
  482. package/src/Grid/Grid.doc.mjs +3 -3
  483. package/src/Grid/Grid.test.tsx +43 -18
  484. package/src/Grid/Grid.tsx +26 -9
  485. package/src/Icon/Icon.test.tsx +41 -29
  486. package/src/Icon/Icon.tsx +6 -2
  487. package/src/InputGroup/InputGroup.tsx +2 -2
  488. package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
  489. package/src/Item/Item.tsx +1 -1
  490. package/src/Layout/Layout.test.tsx +285 -0
  491. package/src/Layout/LayoutContent.doc.mjs +12 -0
  492. package/src/Layout/LayoutPanel.doc.mjs +40 -0
  493. package/src/Layout/LayoutSlots.test.tsx +364 -0
  494. package/src/Layout/__tests__/edgeCompensation.test.tsx +72 -0
  495. package/src/Lightbox/Lightbox.doc.mjs +5 -0
  496. package/src/Lightbox/Lightbox.test.tsx +123 -2
  497. package/src/Lightbox/Lightbox.tsx +29 -1
  498. package/src/Markdown/Markdown.test.tsx +23 -0
  499. package/src/Markdown/Markdown.tsx +9 -7
  500. package/src/Markdown/incremental.test.ts +36 -0
  501. package/src/Markdown/parser.perf.test.ts +34 -12
  502. package/src/Markdown/parser.test.ts +210 -0
  503. package/src/Markdown/parser.ts +301 -6
  504. package/src/MobileNav/MobileNav.doc.mjs +20 -0
  505. package/src/MultiSelector/MultiSelector.doc.mjs +14 -1
  506. package/src/MultiSelector/MultiSelector.test.tsx +33 -0
  507. package/src/MultiSelector/MultiSelector.tsx +20 -0
  508. package/src/NavMenu/NavMenu.doc.mjs +15 -0
  509. package/src/NumberInput/NumberInput.test.tsx +48 -3
  510. package/src/NumberInput/NumberInput.tsx +32 -15
  511. package/src/Outline/parseOutlineFromMarkdown.test.ts +80 -0
  512. package/src/OverflowList/OverflowList.test.tsx +416 -0
  513. package/src/Overlay/Overlay.doc.mjs +6 -0
  514. package/src/Overlay/Overlay.test.tsx +356 -0
  515. package/src/Pagination/Pagination.test.tsx +162 -0
  516. package/src/Pagination/Pagination.tsx +80 -26
  517. package/src/Popover/Popover.test.tsx +65 -0
  518. package/src/PowerSearch/PowerSearch.doc.mjs +4 -4
  519. package/src/PowerSearch/PowerSearch.test.tsx +109 -1
  520. package/src/PowerSearch/PowerSearch.tsx +37 -16
  521. package/src/ProgressBar/ProgressBar.test.tsx +30 -0
  522. package/src/ProgressBar/ProgressBar.tsx +12 -5
  523. package/src/RadioList/RadioList.doc.mjs +7 -1
  524. package/src/RadioList/RadioList.test.tsx +65 -0
  525. package/src/RadioList/RadioList.tsx +10 -1
  526. package/src/RadioList/RadioListItem.tsx +13 -4
  527. package/src/Resizable/ResizeHandle.test.tsx +218 -0
  528. package/src/Resizable/ResizeHandle.tsx +22 -4
  529. package/src/Section/Section.test.tsx +4 -10
  530. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  531. package/src/SegmentedControl/SegmentedControl.test.tsx +192 -0
  532. package/src/SegmentedControl/SegmentedControl.tsx +27 -5
  533. package/src/SegmentedControl/SegmentedControlItem.tsx +9 -4
  534. package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
  535. package/src/Selector/Selector.doc.mjs +12 -1
  536. package/src/Selector/Selector.test.tsx +30 -0
  537. package/src/Selector/Selector.tsx +18 -0
  538. package/src/SideNav/SideNav.doc.mjs +7 -1
  539. package/src/SideNav/SideNav.test.tsx +66 -0
  540. package/src/SideNav/SideNav.tsx +6 -2
  541. package/src/SideNav/SideNavCollapseButton.tsx +4 -3
  542. package/src/SideNav/SideNavSection.tsx +6 -4
  543. package/src/SizeContext/SizeContext.test.tsx +226 -0
  544. package/src/Slider/Slider.doc.mjs +14 -2
  545. package/src/Slider/Slider.test.tsx +30 -0
  546. package/src/Slider/Slider.tsx +20 -0
  547. package/src/Spinner/Spinner.tsx +1 -0
  548. package/src/Switch/Switch.doc.mjs +21 -9
  549. package/src/Switch/Switch.test.tsx +137 -0
  550. package/src/Switch/Switch.tsx +32 -7
  551. package/src/TabList/TabList.doc.mjs +3 -3
  552. package/src/TabList/TabList.test.tsx +185 -1
  553. package/src/TabList/TabMenu.tsx +45 -9
  554. package/src/Table/BaseTable.tsx +16 -3
  555. package/src/Table/Table.test.tsx +87 -0
  556. package/src/Table/TableBody.tsx +15 -2
  557. package/src/Table/TableCell.tsx +87 -8
  558. package/src/Table/TableFooter.tsx +15 -2
  559. package/src/Table/TableHeader.tsx +15 -2
  560. package/src/Table/index.ts +5 -0
  561. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +13 -0
  562. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +3 -1
  563. package/src/Table/plugins/pagination/paginateData.ts +5 -1
  564. package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
  565. package/src/Table/plugins/rowExpansion/index.ts +7 -0
  566. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +155 -0
  567. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +590 -0
  568. package/src/Table/plugins/selection/useTableSelectionState.test.tsx +23 -0
  569. package/src/Table/plugins/selection/useTableSelectionState.tsx +11 -6
  570. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +35 -1
  571. package/src/Table/plugins/sortable/useTableSortableState.tsx +8 -4
  572. package/src/Table/tableContextMenu.test.tsx +27 -3
  573. package/src/Table/tableContextMenu.tsx +20 -2
  574. package/src/Table/useTablePagination.doc.mjs +4 -1
  575. package/src/Table/useTableRowExpansion.doc.mjs +80 -0
  576. package/src/Table/useTableSortable.doc.mjs +4 -1
  577. package/src/Text/Text.doc.mjs +2 -2
  578. package/src/Text/Text.test.tsx +11 -0
  579. package/src/Text/Text.tsx +4 -2
  580. package/src/Text/text.stylex.ts +41 -0
  581. package/src/TextArea/TextArea.doc.mjs +1 -1
  582. package/src/TextArea/TextArea.test.tsx +3 -3
  583. package/src/TextInput/TextInput.doc.mjs +1 -1
  584. package/src/TextInput/TextInput.test.tsx +3 -3
  585. package/src/Thumbnail/Thumbnail.test.tsx +36 -2
  586. package/src/Thumbnail/Thumbnail.tsx +4 -2
  587. package/src/TimeInput/TimeInput.doc.mjs +11 -6
  588. package/src/TimeInput/TimeInput.test.tsx +37 -0
  589. package/src/TimeInput/TimeInput.tsx +11 -1
  590. package/src/Timestamp/Timestamp.doc.mjs +1 -1
  591. package/src/Timestamp/Timestamp.test.tsx +52 -0
  592. package/src/Timestamp/Timestamp.tsx +30 -16
  593. package/src/Toast/Toast.tsx +11 -3
  594. package/src/Toast/ToastViewport.test.tsx +64 -0
  595. package/src/Toast/ToastViewport.tsx +12 -0
  596. package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
  597. package/src/Tokenizer/Tokenizer.doc.mjs +16 -4
  598. package/src/Tokenizer/Tokenizer.test.tsx +33 -0
  599. package/src/Tokenizer/Tokenizer.tsx +19 -0
  600. package/src/Toolbar/Toolbar.test.tsx +1 -1
  601. package/src/TopNav/TopNav.doc.mjs +1 -1
  602. package/src/TopNav/TopNav.test.tsx +18 -0
  603. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +9 -2
  604. package/src/TreeList/TreeList.doc.mjs +2 -2
  605. package/src/Typeahead/BaseTypeahead.doc.mjs +19 -0
  606. package/src/Typeahead/BaseTypeahead.tsx +5 -2
  607. package/src/Typeahead/Typeahead.doc.mjs +7 -2
  608. package/src/Typeahead/Typeahead.test.tsx +45 -1
  609. package/src/__tests__/TestIcon.tsx +26 -0
  610. package/src/__tests__/fastRoleQueries.ts +66 -0
  611. package/src/docPropReferences.test.ts +178 -0
  612. package/src/docs-types.ts +14 -0
  613. package/src/hooks/focusableSelector.ts +1 -1
  614. package/src/hooks/index.ts +3 -0
  615. package/src/hooks/useFocusTrap.doc.mjs +4 -2
  616. package/src/hooks/useFocusTrap.test.tsx +149 -1
  617. package/src/hooks/useFocusTrap.ts +50 -1
  618. package/src/hooks/useHotkeys.doc.mjs +52 -0
  619. package/src/hooks/useHotkeys.test.ts +245 -0
  620. package/src/hooks/useHotkeys.ts +203 -0
  621. package/src/hooks/useInteractiveRole.ts +12 -4
  622. package/src/hooks/useKeyboardHint.doc.mjs +6 -6
  623. package/src/hooks/useStreamingText.test.ts +54 -19
  624. package/src/hooks/useStreamingText.ts +16 -5
  625. package/src/theme/SyntaxTheme.doc.mjs +4 -4
  626. package/src/theme/defineTheme.ts +4 -13
  627. package/src/theme/derivedVarRegistry.test.ts +2 -2
  628. package/src/theme/expandColorScale.test.ts +29 -0
  629. package/src/theme/expandColorScale.ts +11 -6
  630. package/src/theme/hct.ts +9 -17
  631. package/src/theme/tokens.test.ts +182 -9
  632. package/src/theme/tokens.ts +239 -4
  633. package/src/theme/useTheme.test.tsx +20 -0
  634. package/src/utils/color.test.ts +133 -0
  635. package/src/utils/color.ts +148 -0
  636. package/src/utils/composeEventHandlers.test.ts +71 -0
  637. package/src/utils/composeEventHandlers.ts +44 -0
  638. package/src/utils/index.ts +4 -0
  639. package/src/utils/mergeProps.test.ts +166 -0
  640. package/src/utils/sharedResizeObserver.test.ts +2 -2
  641. package/src/utils/timeParser.test.ts +13 -0
  642. package/src/utils/timeParser.ts +8 -5
@@ -62,11 +62,17 @@ export const docs = {
62
62
  description: 'Whether the switch is disabled.',
63
63
  default: 'false',
64
64
  },
65
+ {
66
+ name: 'htmlName',
67
+ type: 'string',
68
+ description:
69
+ 'The HTML name attribute for the underlying checkbox input, useful for form submissions (submits "on" when the switch is on).',
70
+ },
65
71
  {
66
72
  name: 'disabledMessage',
67
73
  type: 'string',
68
74
  description:
69
- 'Explains why the switch is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the switch focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled Switch in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
75
+ 'Explains why the switch is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the switch focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled Switch in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
70
76
  },
71
77
  {
72
78
  name: 'isOptional',
@@ -118,10 +124,10 @@ export const docs = {
118
124
  },
119
125
  {
120
126
  name: 'labelSpacing',
121
- type: "'default' | 'spread'",
127
+ type: "'hug' | 'spread'",
122
128
  description:
123
- 'Spacing behavior between label and switch. "spread" pushes them to opposite ends of the container (full width).',
124
- default: "'default'",
129
+ 'Spacing behavior between label and switch. "hug" places them next to each other; "spread" pushes them to opposite ends of the container (full width). "default" is a deprecated alias for "hug".',
130
+ default: "'hug'",
125
131
  },
126
132
  ],
127
133
  theming: {
@@ -203,11 +209,16 @@ export const docsZh = {
203
209
  description: '开关是否被禁用。',
204
210
  default: 'false',
205
211
  },
212
+ {
213
+ name: 'htmlName',
214
+ type: 'string',
215
+ description: '底层复选框输入的 HTML name 属性,用于表单提交(开启时提交 "on")。',
216
+ },
206
217
  {
207
218
  name: 'disabledMessage',
208
219
  type: 'string',
209
220
  description:
210
- 'Explains why the switch is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the switch focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled Switch in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
221
+ 'Explains why the switch is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the switch focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled Switch in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
211
222
  },
212
223
  {
213
224
  name: 'isOptional',
@@ -259,10 +270,10 @@ export const docsZh = {
259
270
  },
260
271
  {
261
272
  name: 'labelSpacing',
262
- type: "'default' | 'spread'",
273
+ type: "'hug' | 'spread'",
263
274
  description:
264
- '标签和开关之间的间距行为。"spread" 将它们推到容器的两端(全宽)。',
265
- default: "'default'",
275
+ '标签和开关之间的间距行为。"hug" 将它们并排放置;"spread" 将它们推到容器的两端(全宽)。"default" 是 "hug" 的已弃用别名。',
276
+ default: "'hug'",
266
277
  },
267
278
  ],
268
279
  theming: {
@@ -309,6 +320,7 @@ export const docsDense = {
309
320
  isLabelHidden: 'Visually hides label; still accessible to screen readers.',
310
321
  description: 'Description text below label.',
311
322
  isDisabled: 'Whether switch is disabled.',
323
+ htmlName: 'HTML name attr for the checkbox; submits "on" when on.',
312
324
  isOptional: 'Whether field is optional; mutually exclusive w/ isRequired.',
313
325
  isRequired: 'Whether switch is required; mutually exclusive w/ isOptional.',
314
326
  status: 'Status indicator w/ type + message; colored message box, sets aria-invalid on error.',
@@ -317,6 +329,6 @@ export const docsDense = {
317
329
  labelIcon: 'Icon before label text.',
318
330
  labelTooltip: 'Tooltip text in info icon at label end.',
319
331
  labelPosition: 'Which side label appears; "start" places before switch.',
320
- labelSpacing: 'Spacing behavior; "spread" pushes to opposite ends (full width).',
332
+ labelSpacing: 'Spacing behavior; "hug" places next to each other, "spread" pushes to opposite ends (full width). "default" is deprecated alias for "hug".',
321
333
  },
322
334
  };
@@ -470,4 +470,141 @@ describe('Switch', () => {
470
470
  expect(screen.getByRole('switch')).toBeDisabled();
471
471
  });
472
472
  });
473
+ describe('labelSpacing', () => {
474
+ const getField = (container: HTMLElement) =>
475
+ container.querySelector<HTMLElement>('.astryx-switch-field')!;
476
+
477
+ it('omits the data attribute for the default hug spacing', () => {
478
+ const {container} = render(
479
+ <Switch label="Notify" value={false} onChange={() => {}} />,
480
+ );
481
+ expect(getField(container)).not.toHaveAttribute('data-label-spacing');
482
+ });
483
+
484
+ it('reflects spread spacing as a data attribute and variant class', () => {
485
+ const {container} = render(
486
+ <Switch
487
+ label="Notify"
488
+ value={false}
489
+ onChange={() => {}}
490
+ labelSpacing="spread"
491
+ />,
492
+ );
493
+ expect(getField(container)).toHaveAttribute(
494
+ 'data-label-spacing',
495
+ 'spread',
496
+ );
497
+ expect(getField(container).className).toContain('spread');
498
+ });
499
+
500
+ it('renders explicit hug the same as the default', () => {
501
+ const {container: implicit} = render(
502
+ <Switch label="Notify" value={false} onChange={() => {}} />,
503
+ );
504
+ const {container: explicit} = render(
505
+ <Switch
506
+ label="Notify"
507
+ value={false}
508
+ onChange={() => {}}
509
+ labelSpacing="hug"
510
+ />,
511
+ );
512
+ expect(getField(explicit)).not.toHaveAttribute('data-label-spacing');
513
+ expect(getField(explicit).className).toBe(getField(implicit).className);
514
+ });
515
+
516
+ it("treats the deprecated 'default' value as an alias for hug", () => {
517
+ const {container: hug} = render(
518
+ <Switch
519
+ label="Notify"
520
+ value={false}
521
+ onChange={() => {}}
522
+ labelSpacing="hug"
523
+ />,
524
+ );
525
+ const {container: deprecated} = render(
526
+ <Switch
527
+ label="Notify"
528
+ value={false}
529
+ onChange={() => {}}
530
+ labelSpacing="default"
531
+ />,
532
+ );
533
+ expect(getField(deprecated)).not.toHaveAttribute('data-label-spacing');
534
+ expect(getField(deprecated).className).toBe(getField(hug).className);
535
+ // The switch row keeps the hug layout, not the spread justification.
536
+ expect(getField(deprecated).firstElementChild?.className).toBe(
537
+ getField(hug).firstElementChild?.className,
538
+ );
539
+ });
540
+ });
541
+ describe('form participation', () => {
542
+ it('submits under htmlName when on', () => {
543
+ const {container} = render(
544
+ <form>
545
+ <Switch
546
+ label="Notify"
547
+ htmlName="notify"
548
+ value={true}
549
+ onChange={() => {}}
550
+ />
551
+ </form>,
552
+ );
553
+ const data = new FormData(container.querySelector('form')!);
554
+ expect(data.get('notify')).toBe('on');
555
+ });
556
+
557
+ it('is excluded from form data when disabled, even with a disabledMessage', () => {
558
+ const {container} = render(
559
+ <form>
560
+ <Switch
561
+ label="Notify"
562
+ htmlName="notify"
563
+ value={true}
564
+ onChange={() => {}}
565
+ isDisabled
566
+ disabledMessage="Locked"
567
+ />
568
+ </form>,
569
+ );
570
+ expect([
571
+ ...new FormData(container.querySelector('form')!).keys(),
572
+ ]).toEqual([]);
573
+ });
574
+
575
+ it('submits nothing when off or when htmlName is omitted', () => {
576
+ const {container} = render(
577
+ <form>
578
+ <Switch
579
+ label="Off"
580
+ htmlName="off"
581
+ value={false}
582
+ onChange={() => {}}
583
+ />
584
+ <Switch label="Unnamed" value={true} onChange={() => {}} />
585
+ </form>,
586
+ );
587
+ const data = new FormData(container.querySelector('form')!);
588
+ expect([...data.keys()]).toEqual([]);
589
+ });
590
+ });
591
+
592
+ describe('rest forwarding', () => {
593
+ it('forwards data-testid, id, and aria-* to the root element', () => {
594
+ const {container} = render(
595
+ <Switch
596
+ label="Notifications"
597
+ value={false}
598
+ onChange={() => {}}
599
+ data-testid="my-switch"
600
+ id="switch-1"
601
+ aria-label="Toggle notifications"
602
+ />,
603
+ );
604
+ const root = container.querySelector('[data-testid="my-switch"]');
605
+ expect(root).not.toBeNull();
606
+ expect(root).toHaveAttribute('id', 'switch-1');
607
+ expect(root).toHaveAttribute('aria-label', 'Toggle notifications');
608
+ });
609
+ });
473
610
  });
@@ -185,7 +185,11 @@ const styles = stylex.create({
185
185
 
186
186
  export type SwitchLabelPosition = 'start' | 'end';
187
187
 
188
- export type SwitchLabelSpacing = 'default' | 'spread';
188
+ export type SwitchLabelSpacing =
189
+ | 'hug'
190
+ | 'spread'
191
+ /** @deprecated Use `'hug'` instead. */
192
+ | 'default';
189
193
 
190
194
  export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
191
195
  /** Ref forwarded to the root element */
@@ -228,6 +232,13 @@ export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
228
232
  * @default false
229
233
  */
230
234
  isDisabled?: boolean;
235
+
236
+ /**
237
+ * The HTML name attribute for the underlying checkbox input.
238
+ * Useful for form submissions.
239
+ */
240
+ htmlName?: string;
241
+
231
242
  /**
232
243
  * Explains why the switch is disabled. When set together with `isDisabled`,
233
244
  * the switch shows a tooltip with this text on hover and keyboard focus, and
@@ -290,9 +301,11 @@ export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
290
301
  labelPosition?: SwitchLabelPosition;
291
302
  /**
292
303
  * Spacing behavior between label and switch.
293
- * - 'default': Label and switch are positioned next to each other
304
+ * - 'hug': Label and switch are positioned next to each other
294
305
  * - 'spread': Label and switch are pushed to opposite ends
295
- * @default 'default'
306
+ *
307
+ * 'default' is a deprecated alias for 'hug'.
308
+ * @default 'hug'
296
309
  */
297
310
  labelSpacing?: SwitchLabelSpacing;
298
311
  /**
@@ -334,6 +347,7 @@ export function Switch({
334
347
  isLoading = false,
335
348
  value,
336
349
  isDisabled = false,
350
+ htmlName,
337
351
  disabledMessage,
338
352
  isOptional = false,
339
353
  isRequired = false,
@@ -342,13 +356,14 @@ export function Switch({
342
356
  labelIcon,
343
357
  labelTooltip,
344
358
  labelPosition = 'end',
345
- labelSpacing = 'default',
359
+ labelSpacing = 'hug',
346
360
  status,
347
361
  width,
348
362
  xstyle,
349
363
  className,
350
364
  style,
351
365
  ref,
366
+ ...rest
352
367
  }: SwitchProps) {
353
368
  const id = useId();
354
369
  const descriptionID = useId();
@@ -360,6 +375,10 @@ export function Switch({
360
375
 
361
376
  const isOn = optimisticValue === true;
362
377
 
378
+ // 'default' is a deprecated alias for 'hug' (#2889).
379
+ const resolvedLabelSpacing: SwitchLabelSpacing =
380
+ labelSpacing === 'default' ? 'hug' : labelSpacing;
381
+
363
382
  // Disabled-reason tooltip. Disabled controls swallow pointer events, so the
364
383
  // tooltip listeners attach to the switch row (which already exists) and the
365
384
  // native checkbox stays perceivable via aria-disabled instead of the disabled
@@ -395,6 +414,10 @@ export function Switch({
395
414
  id={id}
396
415
  type="checkbox"
397
416
  role="switch"
417
+ // Withhold the name while disabled: with a disabledMessage the
418
+ // input stays focusable (not natively disabled), and a disabled
419
+ // control must not submit.
420
+ name={isDisabled ? undefined : htmlName}
398
421
  checked={isOn}
399
422
  // With a disabledMessage the switch keeps focusability via aria-disabled
400
423
  // so the reason is focus-discoverable; toggling is still blocked by the
@@ -475,12 +498,14 @@ export function Switch({
475
498
  {...mergeProps(
476
499
  themeProps('switch-field', {
477
500
  labelPosition: labelPosition !== 'end' ? labelPosition : undefined,
478
- labelSpacing: labelSpacing !== 'default' ? labelSpacing : undefined,
501
+ labelSpacing:
502
+ resolvedLabelSpacing !== 'hug' ? resolvedLabelSpacing : undefined,
479
503
  }),
480
504
  stylex.props(width != null && dynamicWidthStyles.width(width), xstyle),
481
505
  className,
482
506
  style,
483
- )}>
507
+ )}
508
+ {...rest}>
484
509
  <div
485
510
  ref={el => {
486
511
  // Interaction (hover/focus) listeners for the disabled-message
@@ -493,7 +518,7 @@ export function Switch({
493
518
  }}
494
519
  {...stylex.props(
495
520
  styles.container,
496
- labelSpacing === 'spread' && styles.containerSpread,
521
+ resolvedLabelSpacing === 'spread' && styles.containerSpread,
497
522
  !isDisabled && switchScope,
498
523
  )}>
499
524
  {' '}
@@ -92,7 +92,7 @@ export const docs = {
92
92
  bestPractices: [
93
93
  { guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
94
94
  { guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
95
- { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\u2019t overpower the tab row.' },
95
+ { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\'t overpower the tab row.' },
96
96
  { guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
97
97
  { guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
98
98
  { guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
@@ -113,7 +113,7 @@ export const docsZh = {
113
113
  bestPractices: [
114
114
  { guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
115
115
  { guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
116
- { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\u2019t overpower the tab row.' },
116
+ { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\'t overpower the tab row.' },
117
117
  { guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
118
118
  { guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
119
119
  { guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
@@ -135,7 +135,7 @@ export const docsDense = {
135
135
  bestPractices: [
136
136
  { guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
137
137
  { guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
138
- { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\u2019t overpower the tab row.' },
138
+ { guidance: true, description: 'When using hasDivider with action buttons alongside tabs, use a smaller button size (sm) so the actions don\'t overpower the tab row.' },
139
139
  { guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
140
140
  { guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
141
141
  { guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
13
- import {render, screen} from '@testing-library/react';
13
+ import {render, screen, fireEvent} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {TabList} from './TabList';
16
16
  import {Tab} from './Tab';
@@ -702,3 +702,187 @@ describe('TabMenu', () => {
702
702
  expect(reportsItem).not.toHaveAttribute('aria-current');
703
703
  });
704
704
  });
705
+
706
+ describe('TabMenu keyboard navigation (roving tabindex)', () => {
707
+ const menuOptions = [
708
+ {value: 'analytics', label: 'Analytics'},
709
+ {value: 'reports', label: 'Reports'},
710
+ ];
711
+
712
+ it('exposes the overflow menu as a single Tab stop (one item tabbable, rest -1)', async () => {
713
+ const user = userEvent.setup();
714
+ render(
715
+ <TabList value="home" onChange={() => {}}>
716
+ <Tab value="home" label="Home" />
717
+ <TabMenu label="More" options={menuOptions} />
718
+ </TabList>,
719
+ );
720
+
721
+ await user.click(screen.getByRole('button', {name: /More/}));
722
+
723
+ const analytics = screen.getByRole('menuitem', {
724
+ name: 'Analytics',
725
+ hidden: true,
726
+ });
727
+ const reports = screen.getByRole('menuitem', {
728
+ name: 'Reports',
729
+ hidden: true,
730
+ });
731
+
732
+ // Exactly one menu item is in the Tab sequence; arrow keys reach the rest.
733
+ expect(analytics).toHaveAttribute('tabindex', '0');
734
+ expect(reports).toHaveAttribute('tabindex', '-1');
735
+
736
+ const tabbable = [analytics, reports].filter(
737
+ el => el.getAttribute('tabindex') === '0',
738
+ );
739
+ expect(tabbable).toHaveLength(1);
740
+ });
741
+
742
+ it('moves focus between items with ArrowDown and ArrowUp', async () => {
743
+ const user = userEvent.setup();
744
+ render(
745
+ <TabList value="home" onChange={() => {}}>
746
+ <Tab value="home" label="Home" />
747
+ <TabMenu label="More" options={menuOptions} />
748
+ </TabList>,
749
+ );
750
+
751
+ await user.click(screen.getByRole('button', {name: /More/}));
752
+ const menu = screen.getByRole('menu', {hidden: true});
753
+ const analytics = screen.getByRole('menuitem', {
754
+ name: 'Analytics',
755
+ hidden: true,
756
+ });
757
+ const reports = screen.getByRole('menuitem', {
758
+ name: 'Reports',
759
+ hidden: true,
760
+ });
761
+
762
+ fireEvent.keyDown(menu, {key: 'ArrowDown'});
763
+ expect(analytics).toHaveFocus();
764
+
765
+ fireEvent.keyDown(menu, {key: 'ArrowDown'});
766
+ expect(reports).toHaveFocus();
767
+
768
+ fireEvent.keyDown(menu, {key: 'ArrowUp'});
769
+ expect(analytics).toHaveFocus();
770
+ });
771
+
772
+ it('moves the roving tab stop with arrow navigation', async () => {
773
+ const user = userEvent.setup();
774
+ render(
775
+ <TabList value="home" onChange={() => {}}>
776
+ <Tab value="home" label="Home" />
777
+ <TabMenu label="More" options={menuOptions} />
778
+ </TabList>,
779
+ );
780
+
781
+ await user.click(screen.getByRole('button', {name: /More/}));
782
+ const menu = screen.getByRole('menu', {hidden: true});
783
+ const analytics = screen.getByRole('menuitem', {
784
+ name: 'Analytics',
785
+ hidden: true,
786
+ });
787
+ const reports = screen.getByRole('menuitem', {
788
+ name: 'Reports',
789
+ hidden: true,
790
+ });
791
+
792
+ fireEvent.keyDown(menu, {key: 'ArrowDown'}); // focus analytics
793
+ fireEvent.keyDown(menu, {key: 'ArrowDown'}); // focus reports
794
+
795
+ // The tab stop follows focus, so it is still a single stop after moving.
796
+ expect(reports).toHaveAttribute('tabindex', '0');
797
+ expect(analytics).toHaveAttribute('tabindex', '-1');
798
+ });
799
+
800
+ it('jumps to first and last item with Home and End', async () => {
801
+ const user = userEvent.setup();
802
+ const options = [
803
+ {value: 'analytics', label: 'Analytics'},
804
+ {value: 'reports', label: 'Reports'},
805
+ {value: 'exports', label: 'Exports'},
806
+ ];
807
+ render(
808
+ <TabList value="home" onChange={() => {}}>
809
+ <Tab value="home" label="Home" />
810
+ <TabMenu label="More" options={options} />
811
+ </TabList>,
812
+ );
813
+
814
+ await user.click(screen.getByRole('button', {name: /More/}));
815
+ const menu = screen.getByRole('menu', {hidden: true});
816
+ const analytics = screen.getByRole('menuitem', {
817
+ name: 'Analytics',
818
+ hidden: true,
819
+ });
820
+ const exports = screen.getByRole('menuitem', {
821
+ name: 'Exports',
822
+ hidden: true,
823
+ });
824
+
825
+ fireEvent.keyDown(menu, {key: 'End'});
826
+ expect(exports).toHaveFocus();
827
+
828
+ fireEvent.keyDown(menu, {key: 'Home'});
829
+ expect(analytics).toHaveFocus();
830
+ });
831
+
832
+ it('selects an item with Enter and calls onChange', async () => {
833
+ const user = userEvent.setup();
834
+ const handleChange = vi.fn();
835
+ render(
836
+ <TabList value="home" onChange={handleChange}>
837
+ <Tab value="home" label="Home" />
838
+ <TabMenu label="More" options={menuOptions} />
839
+ </TabList>,
840
+ );
841
+
842
+ await user.click(screen.getByRole('button', {name: /More/}));
843
+ const analytics = screen.getByRole('menuitem', {
844
+ name: 'Analytics',
845
+ hidden: true,
846
+ });
847
+ analytics.focus();
848
+ fireEvent.keyDown(analytics, {key: 'Enter'});
849
+
850
+ expect(handleChange).toHaveBeenCalledWith('analytics');
851
+ });
852
+
853
+ it('closes the menu when Tab is pressed inside it (APG menu-button)', async () => {
854
+ const user = userEvent.setup();
855
+ render(
856
+ <TabList value="home" onChange={() => {}}>
857
+ <Tab value="home" label="Home" />
858
+ <TabMenu label="More" options={menuOptions} />
859
+ </TabList>,
860
+ );
861
+
862
+ await user.click(screen.getByRole('button', {name: /More/}));
863
+ const menu = screen.getByRole('menu', {hidden: true});
864
+
865
+ const hidePopover = vi.mocked(HTMLElement.prototype.hidePopover);
866
+ hidePopover.mockClear();
867
+ fireEvent.keyDown(menu, {key: 'Tab'});
868
+ expect(hidePopover).toHaveBeenCalled();
869
+ });
870
+
871
+ it('closes the menu when Escape is pressed', async () => {
872
+ const user = userEvent.setup();
873
+ render(
874
+ <TabList value="home" onChange={() => {}}>
875
+ <Tab value="home" label="Home" />
876
+ <TabMenu label="More" options={menuOptions} />
877
+ </TabList>,
878
+ );
879
+
880
+ await user.click(screen.getByRole('button', {name: /More/}));
881
+ const menu = screen.getByRole('menu', {hidden: true});
882
+
883
+ const hidePopover = vi.mocked(HTMLElement.prototype.hidePopover);
884
+ hidePopover.mockClear();
885
+ fireEvent.keyDown(menu, {key: 'Escape'});
886
+ expect(hidePopover).toHaveBeenCalled();
887
+ });
888
+ });
@@ -16,7 +16,7 @@
16
16
  * - /packages/cli/templates/blocks/components/TabList/ (showcase blocks)
17
17
  */
18
18
 
19
- import React, {useCallback, useId, type ReactNode} from 'react';
19
+ import React, {useCallback, useId, useRef, type ReactNode} from 'react';
20
20
  import * as stylex from '@stylexjs/stylex';
21
21
  import {Icon} from '../Icon';
22
22
  import {renderIconSlot, type IconType} from '../Icon';
@@ -262,6 +262,7 @@ export function TabMenu({
262
262
  }: TabMenuProps) {
263
263
  const tabListCtx = useTabListContext();
264
264
  const menuId = useId();
265
+ const buttonRef = useRef<HTMLButtonElement>(null);
265
266
 
266
267
  const popover = usePopover({
267
268
  hasLightDismiss: true,
@@ -270,20 +271,50 @@ export function TabMenu({
270
271
  // The popup's own role="menu" is the exposed semantics; a modal dialog
271
272
  // wrapper would announce an unnamed dialog around the menu.
272
273
  role: 'none',
274
+ // Return focus to the trigger when the menu closes (Escape, Tab, select,
275
+ // or light dismiss) so keyboard focus is never dropped to <body>.
276
+ onHide: useCallback(() => {
277
+ buttonRef.current?.focus();
278
+ }, []),
273
279
  });
274
280
 
275
- const {listRef, handleKeyDown: handleListKeyDown} =
276
- useListFocus<HTMLDivElement>({
277
- onEscape: () => popover.hide(),
278
- });
281
+ // The overflow menu is a composite widget: a single roving tab stop with
282
+ // arrow-key navigation between items, per the APG menu pattern. The hook owns
283
+ // item tabindex — items render tabIndex={-1} and exactly one is promoted to 0.
284
+ const {
285
+ listRef,
286
+ handleKeyDown: handleListKeyDown,
287
+ handleFocus,
288
+ focusFirst,
289
+ } = useListFocus<HTMLDivElement>({
290
+ hasRovingTabIndex: true,
291
+ onEscape: () => popover.hide(),
292
+ });
279
293
 
280
294
  const handleToggle = useCallback(() => {
281
295
  if (popover.isOpen) {
282
296
  popover.hide();
283
297
  } else {
284
298
  popover.show();
299
+ // Move focus into the menu on open so arrow navigation works and the
300
+ // roving tab stop lands on a real item (APG menu-button focus-on-open).
301
+ requestAnimationFrame(() => focusFirst());
285
302
  }
286
- }, [popover]);
303
+ }, [popover, focusFirst]);
304
+
305
+ const handleMenuKeyDown = useCallback(
306
+ (e: React.KeyboardEvent) => {
307
+ // APG menu-button: Tab leaves the menu rather than walking its items.
308
+ // Close and let onHide return focus to the trigger, from which the
309
+ // browser's default Tab continues to the next element.
310
+ if (e.key === 'Tab') {
311
+ popover.hide();
312
+ return;
313
+ }
314
+ handleListKeyDown(e);
315
+ },
316
+ [handleListKeyDown, popover],
317
+ );
287
318
 
288
319
  const selectedOption = options.find(o => o.value === tabListCtx.value);
289
320
  const triggerLabel = selectedOption?.label ?? label;
@@ -299,7 +330,11 @@ export function TabMenu({
299
330
  [tabListCtx, popover],
300
331
  );
301
332
 
302
- const setButtonRef = mergeRefs<HTMLButtonElement>(popover.triggerRef, ref);
333
+ const setButtonRef = mergeRefs<HTMLButtonElement>(
334
+ popover.triggerRef,
335
+ buttonRef,
336
+ ref,
337
+ );
303
338
 
304
339
  return (
305
340
  <>
@@ -357,7 +392,8 @@ export function TabMenu({
357
392
  id={menuId}
358
393
  role="menu"
359
394
  aria-label={label}
360
- onKeyDown={handleListKeyDown}
395
+ onKeyDown={handleMenuKeyDown}
396
+ onFocus={handleFocus}
361
397
  {...mergeProps(
362
398
  themeProps('tab-menu-dropdown'),
363
399
  stylex.props(styles.dropdown),
@@ -371,7 +407,7 @@ export function TabMenu({
371
407
  <div
372
408
  key={option.value}
373
409
  role="menuitem"
374
- tabIndex={0}
410
+ tabIndex={-1}
375
411
  aria-current={isSelected ? 'true' : undefined}
376
412
  onClick={() => handleSelect(option.value)}
377
413
  onKeyDown={e => {