@astryxdesign/core 0.1.9 → 0.2.0-canary.136a00f

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 (560) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/Avatar/Avatar.d.ts +42 -3
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +190 -59
  5. package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
  8. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  9. package/dist/AvatarGroup/AvatarGroup.js +58 -6
  10. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  11. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  12. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
  13. package/dist/Banner/Banner.js +2 -2
  14. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
  16. package/dist/Breadcrumbs/index.d.ts +1 -0
  17. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/index.js +2 -1
  19. package/dist/Button/Button.d.ts +1 -1
  20. package/dist/Button/Button.d.ts.map +1 -1
  21. package/dist/Button/Button.js +6 -4
  22. package/dist/Calendar/Calendar.d.ts.map +1 -1
  23. package/dist/Calendar/Calendar.js +50 -9
  24. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  25. package/dist/Calendar/dayCellUtils.js +2 -2
  26. package/dist/Calendar/styles.d.ts +30 -31
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +30 -31
  29. package/dist/Card/Card.js +1 -1
  30. package/dist/Carousel/Carousel.d.ts.map +1 -1
  31. package/dist/Carousel/Carousel.js +22 -12
  32. package/dist/Chat/ChatComposerInput.js +1 -1
  33. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  34. package/dist/Chat/ChatDictationButton.js +3 -1
  35. package/dist/Chat/ChatLayout.js +4 -4
  36. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  37. package/dist/Chat/ChatMessageBubble.js +8 -8
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +10 -3
  40. package/dist/Chat/useTriggerMenu.js +2 -2
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +6 -6
  43. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  44. package/dist/CheckboxList/CheckboxListItem.js +19 -4
  45. package/dist/Citation/Citation.d.ts +22 -1
  46. package/dist/Citation/Citation.d.ts.map +1 -1
  47. package/dist/Citation/Citation.js +20 -6
  48. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  49. package/dist/CodeBlock/CodeBlock.js +16 -10
  50. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  51. package/dist/Collapsible/Collapsible.js +3 -1
  52. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  53. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  54. package/dist/CommandPalette/CommandPalette.js +42 -3
  55. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  56. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  57. package/dist/ContextMenu/ContextMenu.js +23 -5
  58. package/dist/ContextMenu/index.d.ts +1 -0
  59. package/dist/ContextMenu/index.d.ts.map +1 -1
  60. package/dist/ContextMenu/index.js +3 -1
  61. package/dist/DateInput/DateInput.d.ts +10 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +33 -19
  64. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  65. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  66. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  67. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  68. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  69. package/dist/Divider/Divider.d.ts +2 -2
  70. package/dist/Divider/Divider.d.ts.map +1 -1
  71. package/dist/Divider/Divider.js +13 -0
  72. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  73. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  74. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  75. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  76. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  77. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  78. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  79. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
  80. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  81. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
  82. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
  83. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  87. package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
  88. package/dist/DropdownMenu/index.d.ts +10 -0
  89. package/dist/DropdownMenu/index.d.ts.map +1 -1
  90. package/dist/DropdownMenu/index.js +13 -0
  91. package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
  92. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  93. package/dist/DropdownMenu/menuItemHover.js +33 -0
  94. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  95. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  96. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  97. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  98. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  99. package/dist/Field/Field.d.ts +3 -1
  100. package/dist/Field/Field.d.ts.map +1 -1
  101. package/dist/Field/Field.js +4 -1
  102. package/dist/Field/FieldLabel.d.ts +2 -1
  103. package/dist/Field/FieldLabel.d.ts.map +1 -1
  104. package/dist/Field/FieldLabel.js +9 -5
  105. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  106. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  107. package/dist/Field/inputStyles.stylex.js +1 -0
  108. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  109. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  110. package/dist/FieldStatus/FieldStatus.js +39 -3
  111. package/dist/FileInput/FileInput.d.ts +10 -2
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +93 -65
  114. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  115. package/dist/HoverCard/useHoverCard.js +10 -4
  116. package/dist/Icon/Icon.d.ts +15 -1
  117. package/dist/Icon/Icon.d.ts.map +1 -1
  118. package/dist/Icon/Icon.js +19 -3
  119. package/dist/Item/Item.d.ts +16 -3
  120. package/dist/Item/Item.d.ts.map +1 -1
  121. package/dist/Item/Item.js +31 -6
  122. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  123. package/dist/Layer/layerAnimations.stylex.js +10 -2
  124. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  125. package/dist/Lightbox/Lightbox.js +19 -13
  126. package/dist/List/List.d.ts.map +1 -1
  127. package/dist/List/List.js +6 -3
  128. package/dist/List/ListItem.d.ts +11 -1
  129. package/dist/List/ListItem.d.ts.map +1 -1
  130. package/dist/List/ListItem.js +2 -0
  131. package/dist/Markdown/Markdown.d.ts.map +1 -1
  132. package/dist/Markdown/Markdown.js +7 -0
  133. package/dist/MetadataList/MetadataList.d.ts +1 -1
  134. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  135. package/dist/MetadataList/MetadataList.js +4 -2
  136. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  137. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  138. package/dist/MultiSelector/MultiSelector.js +80 -42
  139. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  140. package/dist/NumberInput/NumberInput.d.ts +10 -2
  141. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  142. package/dist/NumberInput/NumberInput.js +22 -17
  143. package/dist/Outline/Outline.js +2 -2
  144. package/dist/Pagination/Pagination.d.ts.map +1 -1
  145. package/dist/Pagination/Pagination.js +11 -3
  146. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  147. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  148. package/dist/PowerSearch/PowerSearch.js +2 -0
  149. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  150. package/dist/ProgressBar/ProgressBar.js +6 -1
  151. package/dist/RadioList/RadioList.d.ts +2 -2
  152. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  153. package/dist/RadioList/RadioListItem.js +5 -5
  154. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  155. package/dist/Resizable/ResizeHandle.js +49 -19
  156. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  157. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  158. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  159. package/dist/Selector/Selector.d.ts +8 -0
  160. package/dist/Selector/Selector.d.ts.map +1 -1
  161. package/dist/Selector/Selector.js +66 -17
  162. package/dist/SideNav/SideNav.d.ts.map +1 -1
  163. package/dist/SideNav/SideNav.js +5 -5
  164. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  165. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  166. package/dist/SideNav/SideNavItem.d.ts +1 -1
  167. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  168. package/dist/SideNav/SideNavItem.js +12 -10
  169. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  170. package/dist/Skeleton/Skeleton.js +2 -2
  171. package/dist/Slider/Slider.d.ts.map +1 -1
  172. package/dist/Slider/Slider.js +87 -34
  173. package/dist/Spinner/Spinner.d.ts +3 -2
  174. package/dist/Spinner/Spinner.d.ts.map +1 -1
  175. package/dist/Spinner/Spinner.js +11 -2
  176. package/dist/Switch/Switch.d.ts +8 -1
  177. package/dist/Switch/Switch.d.ts.map +1 -1
  178. package/dist/Switch/Switch.js +171 -91
  179. package/dist/TabList/Tab.js +2 -2
  180. package/dist/TabList/TabList.d.ts +2 -11
  181. package/dist/TabList/TabList.d.ts.map +1 -1
  182. package/dist/TabList/TabList.js +5 -9
  183. package/dist/TabList/TabListContext.d.ts +0 -5
  184. package/dist/TabList/TabListContext.d.ts.map +1 -1
  185. package/dist/TabList/TabListContext.js +0 -5
  186. package/dist/TabList/TabMenu.js +1 -1
  187. package/dist/Table/BaseTable.d.ts.map +1 -1
  188. package/dist/Table/BaseTable.js +30 -4
  189. package/dist/Table/TableCell.js +3 -3
  190. package/dist/Table/TableHeaderCell.js +3 -3
  191. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  192. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  193. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  194. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
  195. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  196. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  197. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  198. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  199. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  200. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  201. package/dist/Table/types.d.ts +32 -0
  202. package/dist/Table/types.d.ts.map +1 -1
  203. package/dist/TextArea/TextArea.d.ts +10 -1
  204. package/dist/TextArea/TextArea.d.ts.map +1 -1
  205. package/dist/TextArea/TextArea.js +18 -19
  206. package/dist/TextInput/TextInput.d.ts +10 -2
  207. package/dist/TextInput/TextInput.d.ts.map +1 -1
  208. package/dist/TextInput/TextInput.js +20 -17
  209. package/dist/Thumbnail/Thumbnail.js +2 -2
  210. package/dist/TimeInput/TimeInput.d.ts +10 -2
  211. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  212. package/dist/TimeInput/TimeInput.js +17 -17
  213. package/dist/Timestamp/Timestamp.d.ts +31 -3
  214. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  215. package/dist/Timestamp/Timestamp.js +47 -76
  216. package/dist/Timestamp/formatInstant.d.ts +41 -0
  217. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  218. package/dist/Timestamp/formatInstant.js +177 -0
  219. package/dist/Timestamp/index.d.ts +1 -0
  220. package/dist/Timestamp/index.d.ts.map +1 -1
  221. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  222. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  223. package/dist/Timestamp/tooltipEntries.js +163 -0
  224. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  225. package/dist/Toast/ToastViewport.js +61 -9
  226. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  227. package/dist/ToggleButton/ToggleButton.js +3 -1
  228. package/dist/Token/Token.d.ts +34 -4
  229. package/dist/Token/Token.d.ts.map +1 -1
  230. package/dist/Token/Token.js +85 -45
  231. package/dist/Token/TokenLink.d.ts +62 -0
  232. package/dist/Token/TokenLink.d.ts.map +1 -0
  233. package/dist/Token/TokenLink.js +76 -0
  234. package/dist/Token/index.d.ts +1 -1
  235. package/dist/Token/index.d.ts.map +1 -1
  236. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  237. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  238. package/dist/Tokenizer/Tokenizer.js +4 -2
  239. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  240. package/dist/Tooltip/useTooltip.js +17 -1
  241. package/dist/TopNav/TopNavItem.d.ts +3 -1
  242. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  243. package/dist/TopNav/TopNavItem.js +30 -3
  244. package/dist/TreeList/TreeList.d.ts.map +1 -1
  245. package/dist/TreeList/TreeList.js +1 -0
  246. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  247. package/dist/TreeList/TreeListBranches.js +8 -6
  248. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  249. package/dist/TreeList/TreeListItem.js +32 -14
  250. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  251. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  252. package/dist/Typeahead/BaseTypeahead.js +22 -11
  253. package/dist/Typeahead/Typeahead.d.ts +9 -2
  254. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  255. package/dist/Typeahead/Typeahead.js +11 -2
  256. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  257. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  258. package/dist/Typeahead/TypeaheadItem.js +20 -10
  259. package/dist/astryx.css +70 -30
  260. package/dist/astryx.umd.js +51 -51
  261. package/dist/astryx.umd.js.map +4 -4
  262. package/dist/hooks/index.d.ts +2 -0
  263. package/dist/hooks/index.d.ts.map +1 -1
  264. package/dist/hooks/index.js +1 -0
  265. package/dist/hooks/isRtlElement.d.ts +18 -0
  266. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  267. package/dist/hooks/isRtlElement.js +27 -0
  268. package/dist/hooks/useAnnounce.d.ts +3 -0
  269. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  270. package/dist/hooks/useAnnounce.js +39 -1
  271. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  272. package/dist/hooks/useFocusTrap.js +52 -11
  273. package/dist/hooks/useGridFocus.d.ts +6 -1
  274. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  275. package/dist/hooks/useGridFocus.js +12 -9
  276. package/dist/hooks/useHotkeys.d.ts +9 -0
  277. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  278. package/dist/hooks/useHotkeys.js +9 -0
  279. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  280. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  281. package/dist/hooks/useInputStatusIcon.js +158 -0
  282. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  283. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  284. package/dist/hooks/useKeyboardHint.js +4 -2
  285. package/dist/hooks/useListFocus.d.ts +39 -1
  286. package/dist/hooks/useListFocus.d.ts.map +1 -1
  287. package/dist/hooks/useListFocus.js +54 -9
  288. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  289. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  290. package/dist/i18n/InternationalizationContext.js +3 -0
  291. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  292. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  293. package/dist/i18n/InternationalizationProvider.js +5 -1
  294. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  295. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  296. package/dist/i18n/getLocaleDirection.js +29 -0
  297. package/dist/i18n/index.d.ts +6 -0
  298. package/dist/i18n/index.d.ts.map +1 -1
  299. package/dist/i18n/index.js +7 -1
  300. package/dist/i18n/useDirection.d.ts +2 -0
  301. package/dist/i18n/useDirection.d.ts.map +1 -0
  302. package/dist/i18n/useDirection.js +27 -0
  303. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  304. package/dist/theme/derivedVarRegistry.js +13 -0
  305. package/dist/utils/index.d.ts +1 -0
  306. package/dist/utils/index.d.ts.map +1 -1
  307. package/dist/utils/index.js +2 -1
  308. package/dist/utils/plainDate.d.ts +17 -0
  309. package/dist/utils/plainDate.d.ts.map +1 -1
  310. package/dist/utils/plainDate.js +23 -4
  311. package/dist/utils/rtlStyles.d.ts +24 -0
  312. package/dist/utils/rtlStyles.d.ts.map +1 -0
  313. package/dist/utils/rtlStyles.js +27 -0
  314. package/locales/en.json +112 -0
  315. package/locales/pseudo.json +84 -0
  316. package/package.json +6 -1
  317. package/src/Avatar/Avatar.doc.mjs +50 -3
  318. package/src/Avatar/Avatar.test.tsx +218 -0
  319. package/src/Avatar/Avatar.tsx +285 -79
  320. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  321. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  322. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  323. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  324. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  325. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  326. package/src/Banner/Banner.tsx +6 -6
  327. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  328. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  329. package/src/Breadcrumbs/index.ts +4 -0
  330. package/src/Button/Button.doc.mjs +0 -4
  331. package/src/Button/Button.test.tsx +16 -0
  332. package/src/Button/Button.tsx +6 -4
  333. package/src/Calendar/Calendar.test.tsx +170 -20
  334. package/src/Calendar/Calendar.tsx +73 -16
  335. package/src/Calendar/dayCellUtils.test.ts +18 -18
  336. package/src/Calendar/dayCellUtils.ts +2 -2
  337. package/src/Calendar/styles.ts +33 -39
  338. package/src/Card/Card.tsx +1 -1
  339. package/src/Carousel/Carousel.tsx +25 -6
  340. package/src/Chat/ChatComposer.doc.mjs +2 -2
  341. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  342. package/src/Chat/ChatComposerInput.tsx +2 -2
  343. package/src/Chat/ChatDictationButton.tsx +7 -1
  344. package/src/Chat/ChatLayout.tsx +4 -4
  345. package/src/Chat/ChatMessageBubble.tsx +15 -10
  346. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  347. package/src/Chat/ChatToolCalls.tsx +9 -2
  348. package/src/Chat/useTriggerMenu.tsx +1 -1
  349. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  350. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  351. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  352. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  353. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  354. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  355. package/src/Citation/Citation.doc.mjs +4 -3
  356. package/src/Citation/Citation.test.tsx +97 -0
  357. package/src/Citation/Citation.tsx +43 -11
  358. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  359. package/src/CodeBlock/CodeBlock.tsx +38 -11
  360. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  361. package/src/Collapsible/Collapsible.test.tsx +7 -0
  362. package/src/Collapsible/Collapsible.tsx +16 -6
  363. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  364. package/src/CommandPalette/CommandPalette.tsx +41 -2
  365. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  366. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  367. package/src/ContextMenu/ContextMenu.tsx +22 -11
  368. package/src/ContextMenu/index.ts +5 -0
  369. package/src/DateInput/DateInput.doc.mjs +25 -0
  370. package/src/DateInput/DateInput.test.tsx +230 -0
  371. package/src/DateInput/DateInput.tsx +51 -29
  372. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  373. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  374. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  375. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  376. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  377. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  378. package/src/Divider/Divider.test.tsx +32 -8
  379. package/src/Divider/Divider.tsx +14 -1
  380. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  381. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  382. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  383. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  384. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  385. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  386. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
  387. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
  388. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  389. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
  390. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
  391. package/src/DropdownMenu/index.ts +16 -0
  392. package/src/DropdownMenu/menuItemHover.ts +39 -0
  393. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  394. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  395. package/src/Field/Field.tsx +14 -9
  396. package/src/Field/FieldLabel.test.tsx +25 -0
  397. package/src/Field/FieldLabel.tsx +12 -3
  398. package/src/Field/inputStyles.stylex.ts +2 -0
  399. package/src/FieldStatus/FieldStatus.test.tsx +72 -0
  400. package/src/FieldStatus/FieldStatus.tsx +48 -2
  401. package/src/FileInput/FileInput.doc.mjs +23 -2
  402. package/src/FileInput/FileInput.test.tsx +104 -13
  403. package/src/FileInput/FileInput.tsx +106 -79
  404. package/src/HoverCard/useHoverCard.tsx +15 -3
  405. package/src/Icon/Icon.doc.mjs +13 -0
  406. package/src/Icon/Icon.test.tsx +89 -0
  407. package/src/Icon/Icon.tsx +51 -3
  408. package/src/Item/Item.doc.mjs +5 -0
  409. package/src/Item/Item.test.tsx +88 -0
  410. package/src/Item/Item.tsx +57 -11
  411. package/src/Layer/layerAnimations.stylex.ts +23 -0
  412. package/src/Lightbox/Lightbox.tsx +15 -7
  413. package/src/List/List.test.tsx +17 -29
  414. package/src/List/List.tsx +6 -1
  415. package/src/List/ListItem.doc.mjs +12 -0
  416. package/src/List/ListItem.tsx +13 -0
  417. package/src/Markdown/Markdown.test.tsx +21 -0
  418. package/src/Markdown/Markdown.tsx +4 -0
  419. package/src/MetadataList/MetadataList.test.tsx +24 -0
  420. package/src/MetadataList/MetadataList.tsx +6 -2
  421. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  422. package/src/MultiSelector/MultiSelector.test.tsx +402 -0
  423. package/src/MultiSelector/MultiSelector.tsx +120 -59
  424. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  425. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  426. package/src/NumberInput/NumberInput.test.tsx +71 -0
  427. package/src/NumberInput/NumberInput.tsx +35 -26
  428. package/src/Outline/Outline.test.tsx +12 -12
  429. package/src/Outline/Outline.tsx +2 -2
  430. package/src/Pagination/Pagination.tsx +11 -3
  431. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  432. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  433. package/src/PowerSearch/PowerSearch.tsx +10 -1
  434. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  435. package/src/ProgressBar/ProgressBar.tsx +16 -1
  436. package/src/RadioList/RadioList.doc.mjs +6 -0
  437. package/src/RadioList/RadioList.test.tsx +26 -4
  438. package/src/RadioList/RadioList.tsx +2 -2
  439. package/src/RadioList/RadioListItem.tsx +12 -5
  440. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  441. package/src/Resizable/ResizeHandle.tsx +70 -20
  442. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  443. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  444. package/src/Selector/Selector.doc.mjs +15 -0
  445. package/src/Selector/Selector.test.tsx +370 -0
  446. package/src/Selector/Selector.tsx +88 -20
  447. package/src/SideNav/SideNav.tsx +1 -8
  448. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  449. package/src/SideNav/SideNavItem.tsx +5 -3
  450. package/src/Skeleton/Skeleton.test.tsx +16 -0
  451. package/src/Skeleton/Skeleton.tsx +13 -1
  452. package/src/Slider/Slider.doc.mjs +6 -0
  453. package/src/Slider/Slider.test.tsx +240 -12
  454. package/src/Slider/Slider.tsx +96 -23
  455. package/src/Spinner/Spinner.test.tsx +10 -8
  456. package/src/Spinner/Spinner.tsx +15 -5
  457. package/src/Switch/Switch.doc.mjs +142 -42
  458. package/src/Switch/Switch.test.tsx +111 -0
  459. package/src/Switch/Switch.tsx +149 -32
  460. package/src/TabList/Tab.tsx +2 -2
  461. package/src/TabList/TabList.doc.mjs +0 -6
  462. package/src/TabList/TabList.test.tsx +3 -15
  463. package/src/TabList/TabList.tsx +6 -17
  464. package/src/TabList/TabListContext.ts +0 -6
  465. package/src/TabList/TabMenu.tsx +2 -2
  466. package/src/Table/BaseTable.tsx +34 -2
  467. package/src/Table/Table.doc.mjs +11 -0
  468. package/src/Table/Table.test.tsx +85 -0
  469. package/src/Table/TableCell.tsx +3 -3
  470. package/src/Table/TableHeaderCell.tsx +3 -3
  471. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  472. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  473. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
  474. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  475. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  476. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  477. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  478. package/src/Table/types.ts +33 -0
  479. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  480. package/src/TextArea/TextArea.doc.mjs +21 -0
  481. package/src/TextArea/TextArea.test.tsx +23 -0
  482. package/src/TextArea/TextArea.tsx +27 -26
  483. package/src/TextInput/TextInput.doc.mjs +21 -0
  484. package/src/TextInput/TextInput.test.tsx +150 -0
  485. package/src/TextInput/TextInput.tsx +28 -25
  486. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  487. package/src/Thumbnail/Thumbnail.tsx +1 -1
  488. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  489. package/src/TimeInput/TimeInput.test.tsx +23 -0
  490. package/src/TimeInput/TimeInput.tsx +24 -25
  491. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  492. package/src/Timestamp/Timestamp.test.tsx +371 -0
  493. package/src/Timestamp/Timestamp.tsx +96 -93
  494. package/src/Timestamp/formatInstant.ts +218 -0
  495. package/src/Timestamp/index.ts +4 -0
  496. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  497. package/src/Timestamp/tooltipEntries.ts +210 -0
  498. package/src/Toast/ToastViewport.test.tsx +218 -8
  499. package/src/Toast/ToastViewport.tsx +71 -12
  500. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  501. package/src/ToggleButton/ToggleButton.tsx +19 -1
  502. package/src/Token/Token.test.tsx +166 -15
  503. package/src/Token/Token.tsx +104 -47
  504. package/src/Token/TokenLink.tsx +107 -0
  505. package/src/Token/index.ts +1 -1
  506. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  507. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  508. package/src/Tokenizer/Tokenizer.tsx +14 -2
  509. package/src/Tooltip/Tooltip.test.tsx +46 -0
  510. package/src/Tooltip/useTooltip.tsx +20 -0
  511. package/src/TopNav/TopNav.test.tsx +93 -2
  512. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  513. package/src/TopNav/TopNavItem.tsx +35 -6
  514. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  515. package/src/TreeList/TreeList.doc.mjs +6 -0
  516. package/src/TreeList/TreeList.test.tsx +50 -10
  517. package/src/TreeList/TreeList.tsx +5 -0
  518. package/src/TreeList/TreeListBranches.tsx +8 -6
  519. package/src/TreeList/TreeListItem.tsx +33 -11
  520. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  521. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  522. package/src/Typeahead/Typeahead.test.tsx +112 -0
  523. package/src/Typeahead/Typeahead.tsx +17 -1
  524. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  525. package/src/__tests__/forcedColors.ts +60 -0
  526. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  527. package/src/doc-mjs.d.ts +19 -0
  528. package/src/hooks/index.ts +6 -0
  529. package/src/hooks/isRtlElement.ts +27 -0
  530. package/src/hooks/useAnnounce.test.tsx +75 -2
  531. package/src/hooks/useAnnounce.ts +47 -1
  532. package/src/hooks/useFocusTrap.test.tsx +104 -0
  533. package/src/hooks/useFocusTrap.ts +61 -12
  534. package/src/hooks/useGridFocus.doc.mjs +3 -3
  535. package/src/hooks/useGridFocus.test.tsx +41 -0
  536. package/src/hooks/useGridFocus.ts +21 -10
  537. package/src/hooks/useHotkeys.ts +9 -0
  538. package/src/hooks/useInputStatusIcon.test.tsx +162 -0
  539. package/src/hooks/useInputStatusIcon.tsx +224 -0
  540. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  541. package/src/hooks/useKeyboardHint.tsx +6 -2
  542. package/src/hooks/useListFocus.doc.mjs +25 -3
  543. package/src/hooks/useListFocus.test.tsx +153 -1
  544. package/src/hooks/useListFocus.ts +102 -9
  545. package/src/i18n/InternationalizationContext.ts +4 -0
  546. package/src/i18n/InternationalizationProvider.tsx +12 -2
  547. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  548. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  549. package/src/i18n/getLocaleDirection.ts +29 -0
  550. package/src/i18n/index.ts +6 -0
  551. package/src/i18n/useDirection.ts +29 -0
  552. package/src/reset.css +0 -26
  553. package/src/reset.test.ts +60 -0
  554. package/src/theme/derivedVarRegistry.test.ts +1 -0
  555. package/src/theme/derivedVarRegistry.ts +6 -0
  556. package/src/theme/generateThemeRules.test.ts +42 -0
  557. package/src/utils/index.ts +2 -0
  558. package/src/utils/plainDate.test.ts +24 -6
  559. package/src/utils/plainDate.ts +18 -4
  560. package/src/utils/rtlStyles.ts +27 -0
@@ -13,6 +13,10 @@ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
13
  import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {Switch} from './Switch';
16
+ import {
17
+ getAllInjectedCss,
18
+ getForcedColorsRules,
19
+ } from '../__tests__/forcedColors';
16
20
  import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
17
21
 
18
22
  afterEach(() => {
@@ -68,6 +72,28 @@ describe('Switch', () => {
68
72
  expect(screen.getByRole('switch')).toBeChecked();
69
73
  });
70
74
 
75
+ it('renders with custom size prop (sm / md)', () => {
76
+ const {rerender} = render(
77
+ <Switch
78
+ label="Small switch"
79
+ value={false}
80
+ size="sm"
81
+ onChange={() => {}}
82
+ />,
83
+ );
84
+ expect(screen.getByRole('switch')).toBeInTheDocument();
85
+
86
+ rerender(
87
+ <Switch
88
+ label="Medium switch"
89
+ value={false}
90
+ size="md"
91
+ onChange={() => {}}
92
+ />,
93
+ );
94
+ expect(screen.getByRole('switch')).toBeInTheDocument();
95
+ });
96
+
71
97
  it('calls onChange with new checked state when clicked', async () => {
72
98
  const user = userEvent.setup();
73
99
  const handleChange = vi.fn();
@@ -636,6 +662,58 @@ describe('Switch', () => {
636
662
  });
637
663
  });
638
664
 
665
+ describe('RTL thumb travel direction', () => {
666
+ // StyleX injects atomic rules into the document; scan them so we can assert
667
+ // the direction-aware transform without relying on jsdom to resolve the
668
+ // `:is([dir="rtl"] *)` descendant selector against computed style.
669
+ function injectedCss(): string {
670
+ let out = '';
671
+ for (const sheet of Array.from(document.styleSheets)) {
672
+ try {
673
+ for (const rule of Array.from(sheet.cssRules)) {
674
+ out += rule.cssText + '\n';
675
+ }
676
+ } catch {
677
+ // ignore cross-origin sheets
678
+ }
679
+ }
680
+ out += Array.from(document.querySelectorAll('style'))
681
+ .map(s => s.textContent || '')
682
+ .join('\n');
683
+ return out;
684
+ }
685
+
686
+ it('applies a distinct thumb style when on vs off (on-travel is wired)', () => {
687
+ const on = render(<Switch label="On" value={true} onChange={() => {}} />);
688
+ const off = render(
689
+ <Switch label="Off" value={false} onChange={() => {}} />,
690
+ );
691
+ const onThumb = on.container.querySelector(
692
+ '[class*="thumbOnSizeStyles"]',
693
+ );
694
+ const offThumb = off.container.querySelector(
695
+ '[class*="thumbOffSizeStyles"]',
696
+ );
697
+ expect(onThumb).not.toBeNull();
698
+ expect(offThumb).not.toBeNull();
699
+ expect(onThumb!.getAttribute('class')).not.toBe(
700
+ offThumb!.getAttribute('class'),
701
+ );
702
+ });
703
+
704
+ it('mirrors the on-state thumb travel under RTL (negative translateX)', () => {
705
+ render(<Switch label="Toggle" value={true} onChange={() => {}} />);
706
+ const css = injectedCss();
707
+ // LTR on-travel moves the thumb toward the physical right (positive px).
708
+ expect(css).toMatch(/transform:\s*translateX\(1[24]px\)/);
709
+ // RTL mirrors it: the on-thumb lands on the inline-end (physical left)
710
+ // side, so the travel flips sign, scoped to `[dir="rtl"]`.
711
+ expect(css).toMatch(
712
+ /:is\(\[dir="rtl"\][^)]*\)[^{]*\{\s*transform:\s*translateX\(-1[24]px\)/,
713
+ );
714
+ });
715
+ });
716
+
639
717
  describe('rest forwarding', () => {
640
718
  it('forwards data-testid, id, and aria-* to the root element', () => {
641
719
  const {container} = render(
@@ -655,3 +733,36 @@ describe('Switch', () => {
655
733
  });
656
734
  });
657
735
  });
736
+
737
+ // jsdom cannot emulate forced-colors rendering, so these assert that the
738
+ // compiled output includes the forced-colors rules; visual behavior needs
739
+ // manual verification under Windows High Contrast.
740
+ describe('forced colors (WCAG 1.4.11)', () => {
741
+ it('compiles forced-colors overrides so on/off state survives Windows High Contrast', () => {
742
+ render(<Switch label="Notifications" value={true} onChange={() => {}} />);
743
+ const css = getForcedColorsRules();
744
+ // Track outline (backgrounds are stripped; the border keeps the bounds).
745
+ expect(css).toContain('border-color: canvastext;');
746
+ // Off track stays empty; on track uses the selection color.
747
+ expect(css).toContain('background-color: canvas;');
748
+ expect(css).toContain('background-color: highlight;');
749
+ // Thumb fill per state.
750
+ expect(css).toContain('background-color: canvastext;');
751
+ expect(css).toContain('background-color: highlighttext;');
752
+ // Disabled affordance (opacity dimming does not survive forcing).
753
+ expect(css).toContain('border-color: graytext;');
754
+ });
755
+
756
+ it('gates the hover tint out of forced colors so the thumb stays visible on hover', () => {
757
+ render(<Switch label="Notifications" value={true} onChange={() => {}} />);
758
+ // The ancestor-hover tint is a non-system color-mix whose rule outranks the
759
+ // plain forced-colors track rule. It is gated behind `forced-colors: none`
760
+ // so it cannot reassert on hover and flatten the Highlight track to white
761
+ // under the HighlightText thumb (white-on-white).
762
+ expect(getAllInjectedCss()).toContain(
763
+ '(hover: hover) and (forced-colors: none)',
764
+ );
765
+ // And the tint never leaks into the forced-colors output.
766
+ expect(getForcedColorsRules()).not.toContain('color-mix');
767
+ });
768
+ });
@@ -47,17 +47,86 @@ import type {SizeValue} from '../utils/types';
47
47
  import {themeProps} from '../utils/themeProps';
48
48
  import {VisuallyHidden} from '../VisuallyHidden';
49
49
 
50
- // Fixed dimensions: 40px width, 24px height, 16px thumb (off), 20px thumb (on)
51
- const SWITCH_WIDTH = 40;
52
- const SWITCH_HEIGHT = 24;
53
- const THUMB_SIZE_OFF = 16;
54
- const THUMB_SIZE_ON = 20;
55
- const TRACK_PADDING = 4;
56
- // Padding between thumb right edge and track inner edge when on
57
- const ON_RIGHT_PADDING = 2;
58
- // Travel distance for on state: positions thumb with ON_RIGHT_PADDING from right edge
59
- const THUMB_TRAVEL_ON =
60
- SWITCH_WIDTH - TRACK_PADDING - THUMB_SIZE_ON - ON_RIGHT_PADDING;
50
+ const wrapperSizeStyles = stylex.create({
51
+ sm: {
52
+ width: 32,
53
+ height: 20,
54
+ },
55
+ md: {
56
+ width: 40,
57
+ height: 24,
58
+ },
59
+ });
60
+
61
+ const inputSizeStyles = stylex.create({
62
+ sm: {
63
+ width: 32,
64
+ height: 20,
65
+ },
66
+ md: {
67
+ width: 40,
68
+ height: 24,
69
+ },
70
+ });
71
+
72
+ const trackSizeStyles = stylex.create({
73
+ sm: {
74
+ width: 32,
75
+ height: 20,
76
+ padding: 2,
77
+ },
78
+ md: {
79
+ width: 40,
80
+ height: 24,
81
+ padding: 4,
82
+ },
83
+ });
84
+
85
+ const thumbOffSizeStyles = stylex.create({
86
+ sm: {
87
+ width: 14,
88
+ height: 14,
89
+ transform: 'translateX(0)',
90
+ },
91
+ md: {
92
+ width: 16,
93
+ height: 16,
94
+ transform: 'translateX(0)',
95
+ },
96
+ });
97
+
98
+ const thumbOnSizeStyles = stylex.create({
99
+ sm: {
100
+ width: 16,
101
+ height: 16,
102
+ // The thumb rests at the inline-start edge (flex-start, which flexbox
103
+ // already mirrors under RTL). The on-state travel toward the inline-end
104
+ // edge is a physical translateX, so it must flip sign under RTL — right
105
+ // in LTR, left in RTL — so the switch mirrors per convention (Material,
106
+ // iOS): off-thumb on the reading-start side, on-thumb on the reading-end.
107
+ transform: {
108
+ default: 'translateX(12px)',
109
+ ':is([dir="rtl"] *)': 'translateX(-12px)',
110
+ },
111
+ },
112
+ md: {
113
+ width: 20,
114
+ height: 20,
115
+ transform: {
116
+ default: 'translateX(14px)',
117
+ ':is([dir="rtl"] *)': 'translateX(-14px)',
118
+ },
119
+ },
120
+ });
121
+
122
+ const labelWrapperSizeStyles = stylex.create({
123
+ sm: {
124
+ minHeight: 20,
125
+ },
126
+ md: {
127
+ minHeight: 24,
128
+ },
129
+ });
61
130
 
62
131
  const styles = stylex.create({
63
132
  container: {
@@ -77,8 +146,6 @@ const styles = stylex.create({
77
146
  display: 'flex',
78
147
  alignItems: 'center',
79
148
  flexShrink: 0,
80
- width: SWITCH_WIDTH,
81
- height: SWITCH_HEIGHT,
82
149
  isolation: 'isolate',
83
150
  },
84
151
  input: {
@@ -88,8 +155,6 @@ const styles = stylex.create({
88
155
  opacity: 0,
89
156
  cursor: 'pointer',
90
157
  zIndex: 1,
91
- width: SWITCH_WIDTH,
92
- height: SWITCH_HEIGHT,
93
158
  },
94
159
  inputDisabled: {
95
160
  cursor: 'not-allowed',
@@ -100,9 +165,6 @@ const styles = stylex.create({
100
165
  track: {
101
166
  display: 'flex',
102
167
  alignItems: 'center',
103
- width: SWITCH_WIDTH,
104
- height: SWITCH_HEIGHT,
105
- padding: TRACK_PADDING,
106
168
  borderRadius: radiusVars['--radius-full'],
107
169
  transitionProperty: 'background-color',
108
170
  transitionDuration: {
@@ -111,6 +173,21 @@ const styles = stylex.create({
111
173
  },
112
174
  transitionTimingFunction: easeVars['--ease-standard'],
113
175
  boxSizing: 'border-box',
176
+ // Forced colors (Windows High Contrast) strips painted backgrounds, which
177
+ // would leave the track invisible. A system-color border keeps the
178
+ // control's bounds perceivable (WCAG 1.4.11).
179
+ borderWidth: {
180
+ default: 0,
181
+ '@media (forced-colors: active)': '1px',
182
+ },
183
+ borderStyle: {
184
+ default: 'none',
185
+ '@media (forced-colors: active)': 'solid',
186
+ },
187
+ borderColor: {
188
+ default: null,
189
+ '@media (forced-colors: active)': 'CanvasText',
190
+ },
114
191
  },
115
192
  trackFocus: {
116
193
  outline: {
@@ -127,21 +204,39 @@ const styles = stylex.create({
127
204
  trackOff: {
128
205
  backgroundColor: {
129
206
  default: colorVars['--color-background-gray'],
207
+ // Off = empty (Canvas) track; on = Highlight track, so the two states
208
+ // stay distinguishable under forced colors.
209
+ '@media (forced-colors: active)': 'Canvas',
210
+ // The ancestor-hover tint is a non-system color-mix, and its rule
211
+ // outranks the plain forced-colors rule above. Left ungated it would
212
+ // reassert on hover under forced colors, where the UA flattens the
213
+ // color-mix back to Canvas — so the HighlightText thumb would sit on a
214
+ // white track (white-on-white). Gating on `forced-colors: none` keeps
215
+ // the tint out of forced colors and lets the system-color track stand.
130
216
  [stylex.when.ancestor(':hover', switchScope)]: {
131
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-background-gray']}, ${colorVars['--color-tint-hover']} 5%)`,
217
+ '@media (hover: hover) and (forced-colors: none)': `color-mix(in srgb, ${colorVars['--color-background-gray']}, ${colorVars['--color-tint-hover']} 5%)`,
132
218
  },
133
219
  },
134
220
  },
135
221
  trackOn: {
136
222
  backgroundColor: {
137
223
  default: colorVars['--color-accent'],
224
+ '@media (forced-colors: active)': 'Highlight',
225
+ // See trackOff: gate the hover tint out of forced colors so it cannot
226
+ // flatten the Highlight track to white under the HighlightText thumb.
138
227
  [stylex.when.ancestor(':hover', switchScope)]: {
139
- '@media (hover: hover)': `color-mix(in srgb, ${colorVars['--color-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
228
+ '@media (hover: hover) and (forced-colors: none)': `color-mix(in srgb, ${colorVars['--color-accent']}, ${colorVars['--color-tint-hover']} 15%)`,
140
229
  },
141
230
  },
142
231
  },
143
232
  trackDisabled: {
144
233
  opacity: 0.5,
234
+ // Opacity dimming does not survive forced colors; GrayText is the
235
+ // platform's disabled affordance there.
236
+ borderColor: {
237
+ default: null,
238
+ '@media (forced-colors: active)': 'GrayText',
239
+ },
145
240
  },
146
241
  trackDisabledOff: {
147
242
  backgroundColor: colorVars['--color-background-gray'],
@@ -151,7 +246,6 @@ const styles = stylex.create({
151
246
  alignItems: 'center',
152
247
  justifyContent: 'center',
153
248
  borderRadius: radiusVars['--radius-full'],
154
- backgroundColor: colorVars['--color-background-surface'],
155
249
  transitionProperty: 'transform, width, height',
156
250
  transitionDuration: {
157
251
  default: durationVars['--duration-fast'],
@@ -159,22 +253,27 @@ const styles = stylex.create({
159
253
  },
160
254
  transitionTimingFunction: easeVars['--ease-standard'],
161
255
  },
256
+ // The thumb fill lives on the on/off styles (not the shared thumb style)
257
+ // because forced colors needs a per-state system color: CanvasText on the
258
+ // empty off track, HighlightText on the Highlight on track. Sizing stays in
259
+ // thumbOffSizeStyles/thumbOnSizeStyles; only the fill is state-dependent.
162
260
  thumbOff: {
163
- width: THUMB_SIZE_OFF,
164
- height: THUMB_SIZE_OFF,
165
- transform: 'translateX(0)',
261
+ backgroundColor: {
262
+ default: colorVars['--color-background-surface'],
263
+ '@media (forced-colors: active)': 'CanvasText',
264
+ },
166
265
  },
167
266
  thumbOn: {
168
- width: THUMB_SIZE_ON,
169
- height: THUMB_SIZE_ON,
170
- transform: `translateX(${THUMB_TRAVEL_ON}px)`,
267
+ backgroundColor: {
268
+ default: colorVars['--color-background-surface'],
269
+ '@media (forced-colors: active)': 'HighlightText',
270
+ },
171
271
  },
172
272
  labelWrapper: {
173
273
  display: 'flex',
174
274
  flexDirection: 'column',
175
275
  gap: spacingVars['--spacing-0-5'],
176
276
  justifyContent: 'center',
177
- minHeight: SWITCH_HEIGHT,
178
277
  },
179
278
  description: {
180
279
  fontFamily: typographyVars['--font-family-body'],
@@ -313,6 +412,13 @@ export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
313
412
  * When set with a message, displays a colored message box below the switch.
314
413
  */
315
414
  status?: InputStatus;
415
+ /**
416
+ * Size variant controlling track and thumb dimensions.
417
+ * - 'sm': 34x20px (matches sm checkbox/radio vertical rhythm)
418
+ * - 'md': 40x24px (default, matches md checkbox/radio vertical rhythm)
419
+ * @default 'md'
420
+ */
421
+ size?: 'sm' | 'md';
316
422
  }
317
423
 
318
424
  // Dynamic field width (number -> px, string used as-is).
@@ -358,6 +464,7 @@ export function Switch({
358
464
  labelPosition = 'end',
359
465
  labelSpacing = 'hug',
360
466
  status,
467
+ size = 'md',
361
468
  width,
362
469
  xstyle,
363
470
  className,
@@ -410,7 +517,7 @@ export function Switch({
410
517
  describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
411
518
 
412
519
  const switchElement = (
413
- <div {...stylex.props(styles.switchWrapper)}>
520
+ <div {...stylex.props(styles.switchWrapper, wrapperSizeStyles[size])}>
414
521
  <input
415
522
  ref={mergeRefs(ref, disabledMessageTooltip.positionRef)}
416
523
  id={id}
@@ -447,6 +554,7 @@ export function Switch({
447
554
  aria-busy={isBusy || undefined}
448
555
  {...stylex.props(
449
556
  styles.input,
557
+ inputSizeStyles[size],
450
558
  isDisabled && styles.inputDisabled,
451
559
  isBusy && styles.inputBusy,
452
560
  )}
@@ -457,9 +565,11 @@ export function Switch({
457
565
  themeProps('switch', {
458
566
  checked: isOn ? 'checked' : null,
459
567
  disabled: isDisabled ? 'disabled' : null,
568
+ size,
460
569
  }),
461
570
  stylex.props(
462
571
  styles.track,
572
+ trackSizeStyles[size],
463
573
  isOn ? styles.trackOn : styles.trackOff,
464
574
  !isDisabled && styles.trackFocus,
465
575
  isDisabled && styles.trackDisabled,
@@ -468,8 +578,15 @@ export function Switch({
468
578
  )}>
469
579
  <div
470
580
  {...mergeProps(
471
- themeProps('switch-thumb', {checked: isOn ? 'checked' : null}),
472
- stylex.props(styles.thumb, isOn ? styles.thumbOn : styles.thumbOff),
581
+ themeProps('switch-thumb', {
582
+ checked: isOn ? 'checked' : null,
583
+ size,
584
+ }),
585
+ stylex.props(
586
+ styles.thumb,
587
+ isOn ? thumbOnSizeStyles[size] : thumbOffSizeStyles[size],
588
+ isOn ? styles.thumbOn : styles.thumbOff,
589
+ ),
473
590
  )}>
474
591
  {isBusy && <Spinner size="sm" />}
475
592
  </div>
@@ -479,7 +596,7 @@ export function Switch({
479
596
  );
480
597
 
481
598
  const labelElement = (
482
- <div {...stylex.props(styles.labelWrapper)}>
599
+ <div {...stylex.props(styles.labelWrapper, labelWrapperSizeStyles[size])}>
483
600
  <FieldLabel
484
601
  label={label}
485
602
  inputID={id}
@@ -143,8 +143,8 @@ const styles = stylex.create({
143
143
  // with a bottom divider — that ancestor sets `--_tab-indicator-bottom`
144
144
  // to drop the indicator onto the rail beneath the reserved gap.
145
145
  bottom: 'var(--_tab-indicator-bottom, -1px)',
146
- left: spacingVars['--spacing-3'],
147
- right: spacingVars['--spacing-3'],
146
+ insetInlineStart: spacingVars['--spacing-3'],
147
+ insetInlineEnd: spacingVars['--spacing-3'],
148
148
  height: '2px',
149
149
  borderRadius: radiusVars['--radius-full'],
150
150
  pointerEvents: 'none',
@@ -55,12 +55,6 @@ export const docs = {
55
55
  description: 'Whether to show a bottom border divider under the tab list.',
56
56
  default: 'false',
57
57
  },
58
- {
59
- name: 'orientation',
60
- type: "'horizontal' | 'vertical'",
61
- description: "Orientation of the tab strip, controlling which arrow keys move focus between tabs and the reported aria-orientation. 'horizontal': ArrowLeft/ArrowRight. 'vertical': ArrowUp/ArrowDown. Both axes' arrows are accepted regardless.",
62
- default: "'horizontal'",
63
- },
64
58
  {
65
59
  name: 'children',
66
60
  type: 'ReactNode',
@@ -77,10 +77,9 @@ describe('TabList', () => {
77
77
 
78
78
  it('does not set aria-orientation on the nav (invalid for role navigation)', () => {
79
79
  // Regression: aria-orientation is not an allowed attribute on the
80
- // navigation role and produces an axe aria-allowed-attr violation. The
81
- // `orientation` prop must drive keyboard/hint behavior without emitting
82
- // this attribute, regardless of the value passed.
83
- const {rerender} = render(
80
+ // navigation role and produces an axe aria-allowed-attr violation.
81
+ // TabList deliberately never sets this attribute.
82
+ render(
84
83
  <TabList value="home" onChange={() => {}}>
85
84
  <Tab value="home" label="Home" />
86
85
  <Tab value="settings" label="Settings" />
@@ -90,17 +89,6 @@ describe('TabList', () => {
90
89
  expect(screen.getByRole('navigation')).not.toHaveAttribute(
91
90
  'aria-orientation',
92
91
  );
93
-
94
- rerender(
95
- <TabList value="home" onChange={() => {}} orientation="vertical">
96
- <Tab value="home" label="Home" />
97
- <Tab value="settings" label="Settings" />
98
- </TabList>,
99
- );
100
-
101
- expect(screen.getByRole('navigation')).not.toHaveAttribute(
102
- 'aria-orientation',
103
- );
104
92
  });
105
93
 
106
94
  it('ignores a consumer-supplied aria-orientation on the nav', () => {
@@ -22,7 +22,7 @@ import * as stylex from '@stylexjs/stylex';
22
22
  import {borderVars, colorVars, spacingVars} from '../theme/tokens.stylex';
23
23
  import type {BaseProps} from '../BaseProps';
24
24
  import {TabListContext} from './TabListContext';
25
- import type {TabListOrientation, TabListSize} from './TabListContext';
25
+ import type {TabListSize} from './TabListContext';
26
26
  import {useSize} from '../SizeContext/SizeContext';
27
27
  import {mergeProps, mergeRefs} from '../utils';
28
28
  import {useListFocus} from '../hooks/useListFocus';
@@ -66,15 +66,6 @@ export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
66
66
  * @default false
67
67
  */
68
68
  hasDivider?: boolean;
69
- /**
70
- * Orientation of the tab strip, controlling which arrow keys move
71
- * focus between tabs.
72
- * - `'horizontal'` (default): ArrowLeft / ArrowRight (ArrowUp / ArrowDown
73
- * also work per the WAI-ARIA APG).
74
- * - `'vertical'`: ArrowUp / ArrowDown (ArrowLeft / ArrowRight also work).
75
- * @default 'horizontal'
76
- */
77
- orientation?: TabListOrientation;
78
69
  /**
79
70
  * Tab and TabMenu children.
80
71
  */
@@ -130,7 +121,6 @@ export function TabList({
130
121
  size: sizeProp,
131
122
  layout = 'hug',
132
123
  hasDivider = false,
133
- orientation = 'horizontal',
134
124
  xstyle,
135
125
  className,
136
126
  style,
@@ -150,14 +140,13 @@ export function TabList({
150
140
  // Roving-tabindex keyboard navigation across the tab strip via the shared
151
141
  // hook. `orientation: 'both'` accepts both arrow axes per the WAI-ARIA APG
152
142
  // allowance for tab strips (ArrowRight/ArrowDown advance, ArrowLeft/ArrowUp
153
- // retreat) regardless of the component's `orientation` prop, which only
154
- // drives the keyboard hint badge (see useKeyboardHint below). We do not set
155
- // `aria-orientation` on the `<nav>`: that attribute is invalid on the
156
- // navigation role and triggers an axe `aria-allowed-attr` violation.
143
+ // retreat). We do not set `aria-orientation` on the `<nav>`: that attribute
144
+ // is invalid on the navigation role and triggers an axe `aria-allowed-attr`
145
+ // violation.
157
146
  //
158
147
  // `hasRovingTabIndex` makes the hook own the single tab stop: it stamps
159
148
  // tabindex 0/-1, repairs the stop on mount and as stops mount/unmount or
160
- // toggle disabled, and — via `handleFocus` on the nav — keeps the stop in
149
+ // toggle disabled, and -- via `handleFocus` on the nav -- keeps the stop in
161
150
  // sync after clicks or programmatic focus. Individual Tabs still render
162
151
  // `tabIndex={isSelected ? 0 : -1}` (see Tab.tsx) as the initial source of
163
152
  // truth; the hook's repair preserves an existing tab stop and only promotes
@@ -173,7 +162,7 @@ export function TabList({
173
162
  onKeyDown: onHintKeyDown,
174
163
  onFocus: onHintFocus,
175
164
  onBlur: onHintBlur,
176
- } = useKeyboardHint({orientation});
165
+ } = useKeyboardHint();
177
166
 
178
167
  const contextValue = useMemo(
179
168
  () => ({value, onChange, size, layout}),
@@ -26,12 +26,6 @@ export type TabListSize = 'sm' | 'md' | 'lg';
26
26
  */
27
27
  export type TabListLayout = 'hug' | 'fill';
28
28
 
29
- /**
30
- * Orientation of the tab strip. Controls which arrow keys move focus
31
- * between tabs and the reported `aria-orientation`.
32
- */
33
- export type TabListOrientation = 'horizontal' | 'vertical';
34
-
35
29
  /**
36
30
  * Context for communicating value/onChange/size/layout from TabList to children.
37
31
  */
@@ -126,8 +126,8 @@ const styles = stylex.create({
126
126
  // drops onto the divider rail when an ancestor (TabList `hasDivider` or a
127
127
  // Toolbar with a bottom divider) sets `--_tab-indicator-bottom`.
128
128
  bottom: 'var(--_tab-indicator-bottom, -1px)',
129
- left: spacingVars['--spacing-3'],
130
- right: spacingVars['--spacing-3'],
129
+ insetInlineStart: spacingVars['--spacing-3'],
130
+ insetInlineEnd: spacingVars['--spacing-3'],
131
131
  height: '2px',
132
132
  borderRadius: radiusVars['--radius-full'],
133
133
  pointerEvents: 'none',
@@ -134,6 +134,12 @@ interface TableRowProps<T extends Record<string, unknown>> {
134
134
  textOverflow: 'wrap' | 'truncate';
135
135
  RowComponent: React.ComponentType<TableRowComponentProps>;
136
136
  CellComponent: React.ComponentType<TableCellComponentProps>;
137
+ /**
138
+ * 1-based ARIA row index for this row's position in the full dataset.
139
+ * `undefined` when the table hasn't opted into ARIA row indexing, in which
140
+ * case no `aria-rowindex` is emitted (native table semantics).
141
+ */
142
+ ariaRowIndex?: number;
137
143
  }
138
144
 
139
145
  /**
@@ -150,6 +156,7 @@ function TableRowInner<T extends Record<string, unknown>>({
150
156
  textOverflow,
151
157
  RowComponent,
152
158
  CellComponent,
159
+ ariaRowIndex,
153
160
  }: TableRowProps<T>): ReactElement {
154
161
  // Build cells first
155
162
  const cells = columns.map((col, columnIndex) => {
@@ -211,12 +218,14 @@ function TableRowInner<T extends Record<string, unknown>>({
211
218
  );
212
219
  });
213
220
 
214
- // Apply plugin transforms for row (with pre-rendered children)
221
+ // Apply plugin transforms for row (with pre-rendered children).
222
+ // Seed `aria-rowindex` (when the table opts into ARIA row indexing) as a
223
+ // base htmlProp so plugins compose over it and can still override.
215
224
  const rowRenderProps = applyPlugins(
216
225
  plugins,
217
226
  p => p.transformBodyRow,
218
227
  {
219
- htmlProps: {},
228
+ htmlProps: ariaRowIndex == null ? {} : {'aria-rowindex': ariaRowIndex},
220
229
  xstyle: [],
221
230
  children: <>{cells}</>,
222
231
  } satisfies BodyRowRenderProps,
@@ -256,6 +265,9 @@ function areRowPropsEqual<T extends Record<string, unknown>>(
256
265
  if (prevProps.rowIndex !== nextProps.rowIndex) {
257
266
  return false;
258
267
  }
268
+ if (prevProps.ariaRowIndex !== nextProps.ariaRowIndex) {
269
+ return false;
270
+ }
259
271
 
260
272
  if (prevProps.columns !== nextProps.columns) {
261
273
  return false;
@@ -323,6 +335,8 @@ function BaseTableInner<T extends Record<string, unknown>>({
323
335
  textOverflow = 'wrap',
324
336
  scrollWrapper: ScrollWrapper,
325
337
  emptyState,
338
+ rowIndexStart,
339
+ rowCount,
326
340
  xstyle,
327
341
  className,
328
342
  style,
@@ -333,6 +347,18 @@ function BaseTableInner<T extends Record<string, unknown>>({
333
347
  // Use stable empty array when no plugins provided
334
348
  const plugins = pluginsProp ?? (EMPTY_PLUGINS as TablePlugin<T>[]);
335
349
 
350
+ // ARIA row indexing. The row ordinal is an accessibility concern that is
351
+ // independent of any visible index column: when the consumer opts in (by
352
+ // passing rowIndexStart or rowCount), body rows carry `aria-rowindex`
353
+ // reflecting their position in the full dataset, and the <table> carries
354
+ // `aria-rowcount`. `aria-rowindex` is 1-based and counts data rows from
355
+ // `rowIndexStart` (default 1); a windowed/paginated view passes the offset
356
+ // of its first visible row. `aria-rowcount` is `rowCount` when known, or
357
+ // `-1` (ARIA's "unknown count") for a windowed view with an unknown total.
358
+ const ariaRowIndexingEnabled = rowIndexStart != null || rowCount != null;
359
+ const firstRowAriaIndex = rowIndexStart ?? 1;
360
+ const ariaRowCount = ariaRowIndexingEnabled ? (rowCount ?? -1) : undefined;
361
+
336
362
  const RowComponent = TableRow as React.ComponentType<TableRowComponentProps>;
337
363
  const CellComponent =
338
364
  TableCell as React.ComponentType<TableCellComponentProps>;
@@ -486,6 +512,7 @@ function BaseTableInner<T extends Record<string, unknown>>({
486
512
  let tableElement: ReactNode = (
487
513
  <table
488
514
  ref={ref}
515
+ {...(ariaRowCount != null ? {'aria-rowcount': ariaRowCount} : null)}
489
516
  {...tableRenderProps.htmlProps}
490
517
  {...mergeProps(
491
518
  themeProps('base-table'),
@@ -530,6 +557,11 @@ function BaseTableInner<T extends Record<string, unknown>>({
530
557
  textOverflow={textOverflow}
531
558
  RowComponent={RowComponent}
532
559
  CellComponent={CellComponent}
560
+ ariaRowIndex={
561
+ ariaRowIndexingEnabled
562
+ ? firstRowAriaIndex + rowIndex
563
+ : undefined
564
+ }
533
565
  />
534
566
  );
535
567
  })