@astryxdesign/core 0.4.5 → 0.4.6-canary.cea9ecd

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 (538) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/dist/Avatar/Avatar.d.ts +10 -5
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +139 -30
  5. package/dist/Avatar/AvatarStatusDot.d.ts +2 -1
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/Avatar/AvatarStatusDot.js +30 -4
  8. package/dist/Avatar/AvatarStatusLabelContext.d.ts +39 -0
  9. package/dist/Avatar/AvatarStatusLabelContext.d.ts.map +1 -0
  10. package/dist/Avatar/AvatarStatusLabelContext.js +41 -0
  11. package/dist/AvatarGroup/AvatarGroup.d.ts +3 -1
  12. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  13. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  14. package/dist/AvatarGroup/AvatarGroupOverflow.js +15 -9
  15. package/dist/Blockquote/Blockquote.d.ts +4 -3
  16. package/dist/Blockquote/Blockquote.d.ts.map +1 -1
  17. package/dist/Blockquote/Blockquote.js +9 -10
  18. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  19. package/dist/BottomSheet/BottomSheetPanel.js +21 -5
  20. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  21. package/dist/Breadcrumbs/BreadcrumbItem.js +47 -34
  22. package/dist/Button/Button.d.ts.map +1 -1
  23. package/dist/Button/Button.js +7 -7
  24. package/dist/Calendar/Calendar.d.ts.map +1 -1
  25. package/dist/Calendar/Calendar.js +21 -12
  26. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  27. package/dist/Calendar/hooks/useCalendarNavigation.js +8 -4
  28. package/dist/Calendar/styles.d.ts +2 -2
  29. package/dist/Calendar/styles.d.ts.map +1 -1
  30. package/dist/Calendar/styles.js +5 -5
  31. package/dist/Center/Center.d.ts +23 -1
  32. package/dist/Center/Center.d.ts.map +1 -1
  33. package/dist/Center/Center.js +12 -6
  34. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  35. package/dist/Chat/ChatComposer.js +3 -3
  36. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  37. package/dist/Chat/ChatComposerDrawer.js +2 -2
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +2 -2
  40. package/dist/Chat/useChatDictation.d.ts +1 -1
  41. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  42. package/dist/Chat/useSpeechRecognition.d.ts +1 -1
  43. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  44. package/dist/Chat/useSpeechRecognition.js +4 -3
  45. package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
  46. package/dist/Chat/useTriggerMenu.js +2 -2
  47. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  48. package/dist/CheckboxInput/CheckboxInput.js +2 -2
  49. package/dist/Citation/Citation.d.ts.map +1 -1
  50. package/dist/Citation/Citation.js +5 -5
  51. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  52. package/dist/ClickableCard/ClickableCard.js +4 -4
  53. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  54. package/dist/CodeBlock/CodeBlock.js +1 -1
  55. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  56. package/dist/Collapsible/Collapsible.js +2 -2
  57. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  58. package/dist/CommandPalette/CommandPaletteItem.js +3 -3
  59. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  60. package/dist/ComplexSelector/ComplexSelector.js +6 -6
  61. package/dist/DateInput/DateInput.d.ts +31 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +90 -22
  64. package/dist/DateInput/MonthScroller.d.ts +35 -0
  65. package/dist/DateInput/MonthScroller.d.ts.map +1 -0
  66. package/dist/DateInput/MonthScroller.js +658 -0
  67. package/dist/DateInput/MonthYearWheels.d.ts +24 -0
  68. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -0
  69. package/dist/DateInput/MonthYearWheels.js +114 -0
  70. package/dist/DateInput/TouchDateField.d.ts +10 -0
  71. package/dist/DateInput/TouchDateField.d.ts.map +1 -0
  72. package/dist/DateInput/TouchDateField.js +810 -0
  73. package/dist/DateInput/Wheel.d.ts +41 -0
  74. package/dist/DateInput/Wheel.d.ts.map +1 -0
  75. package/dist/DateInput/Wheel.js +315 -0
  76. package/dist/DateInput/monthGeometry.d.ts +65 -0
  77. package/dist/DateInput/monthGeometry.d.ts.map +1 -0
  78. package/dist/DateInput/monthGeometry.js +98 -0
  79. package/dist/DateInput/tokens.stylex.d.ts +63 -0
  80. package/dist/DateInput/tokens.stylex.d.ts.map +1 -0
  81. package/dist/DateInput/tokens.stylex.js +74 -0
  82. package/dist/DateInput/useOwnScrollGesture.d.ts +41 -0
  83. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -0
  84. package/dist/DateInput/useOwnScrollGesture.js +202 -0
  85. package/dist/DateInput/usePointerDragScroll.d.ts +15 -0
  86. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -0
  87. package/dist/DateInput/usePointerDragScroll.js +216 -0
  88. package/dist/DateInput/useScrollSettle.d.ts +26 -0
  89. package/dist/DateInput/useScrollSettle.d.ts.map +1 -0
  90. package/dist/DateInput/useScrollSettle.js +149 -0
  91. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  92. package/dist/DateRangeInput/DateRangeInput.js +17 -14
  93. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  94. package/dist/DateTimeInput/DateTimeInput.js +17 -14
  95. package/dist/Dialog/Dialog.d.ts.map +1 -1
  96. package/dist/Dialog/Dialog.js +3 -3
  97. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  98. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +2 -2
  99. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  100. package/dist/DropdownMenu/DropdownMenuItem.js +2 -2
  101. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  102. package/dist/DropdownMenu/DropdownMenuRadioItem.js +2 -2
  103. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  104. package/dist/DropdownMenu/DropdownMenuSubMenu.js +2 -2
  105. package/dist/Field/FieldLabel.d.ts.map +1 -1
  106. package/dist/Field/FieldLabel.js +4 -4
  107. package/dist/Field/InputClearButton.d.ts.map +1 -1
  108. package/dist/Field/InputClearButton.js +6 -0
  109. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  110. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  111. package/dist/Field/inputStyles.stylex.js +5 -5
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +6 -6
  114. package/dist/HoverCard/HoverCard.d.ts +13 -3
  115. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  116. package/dist/HoverCard/HoverCard.js +2 -0
  117. package/dist/HoverCard/index.d.ts +1 -1
  118. package/dist/HoverCard/index.d.ts.map +1 -1
  119. package/dist/HoverCard/useHoverCard.d.ts +17 -2
  120. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  121. package/dist/HoverCard/useHoverCard.js +78 -9
  122. package/dist/InputGroup/InputGroup.js +1 -1
  123. package/dist/Item/Item.d.ts +9 -1
  124. package/dist/Item/Item.d.ts.map +1 -1
  125. package/dist/Item/Item.js +52 -14
  126. package/dist/Layer/index.d.ts +4 -2
  127. package/dist/Layer/index.d.ts.map +1 -1
  128. package/dist/Layer/index.js +2 -0
  129. package/dist/Layer/useLayer.d.ts.map +1 -1
  130. package/dist/Layer/useLayer.js +3 -2
  131. package/dist/Layer/useTouchTrigger.d.ts +113 -0
  132. package/dist/Layer/useTouchTrigger.d.ts.map +1 -0
  133. package/dist/Layer/useTouchTrigger.js +241 -0
  134. package/dist/Layout/container.stylex.d.ts +4 -2
  135. package/dist/Layout/container.stylex.d.ts.map +1 -1
  136. package/dist/Layout/container.stylex.js +19 -11
  137. package/dist/Layout/index.d.ts +1 -0
  138. package/dist/Layout/index.d.ts.map +1 -1
  139. package/dist/Layout/index.js +4 -0
  140. package/dist/Layout/padding.stylex.d.ts +315 -12
  141. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  142. package/dist/Layout/padding.stylex.js +389 -12
  143. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  144. package/dist/Lightbox/Lightbox.js +5 -4
  145. package/dist/Link/Link.d.ts.map +1 -1
  146. package/dist/Link/Link.js +6 -6
  147. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  148. package/dist/MetadataList/MetadataList.js +1 -1
  149. package/dist/MobileNav/MobileNav.d.ts +1 -0
  150. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  151. package/dist/MobileNav/MobileNav.js +24 -6
  152. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  153. package/dist/MultiSelector/MultiSelector.js +8 -8
  154. package/dist/NavItem/navItemStyles.stylex.d.ts +4 -4
  155. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  156. package/dist/NavItem/navItemStyles.stylex.js +4 -4
  157. package/dist/NavMenu/NavHeadingMenuItem.d.ts.map +1 -1
  158. package/dist/NavMenu/NavHeadingMenuItem.js +3 -3
  159. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  160. package/dist/NumberInput/NumberInput.js +36 -8
  161. package/dist/Outline/Outline.d.ts.map +1 -1
  162. package/dist/Outline/Outline.js +3 -3
  163. package/dist/Pagination/Pagination.d.ts.map +1 -1
  164. package/dist/Pagination/Pagination.js +2 -2
  165. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearch.js +11 -12
  167. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  169. package/dist/PowerSearch/formatFilterValue.d.ts +11 -2
  170. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  171. package/dist/PowerSearch/formatFilterValue.js +23 -8
  172. package/dist/RadioList/RadioListItem.d.ts +2 -2
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +70 -40
  175. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  176. package/dist/Resizable/ResizeHandle.js +7 -7
  177. package/dist/Section/Section.d.ts +36 -1
  178. package/dist/Section/Section.d.ts.map +1 -1
  179. package/dist/Section/Section.js +12 -2
  180. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  181. package/dist/SegmentedControl/SegmentedControlItem.js +7 -2
  182. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  183. package/dist/SelectableCard/SelectableCard.js +3 -3
  184. package/dist/Selector/Selector.d.ts +26 -1
  185. package/dist/Selector/Selector.d.ts.map +1 -1
  186. package/dist/Selector/Selector.js +93 -20
  187. package/dist/Selector/SelectorOption.d.ts +14 -1
  188. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  189. package/dist/Selector/SelectorOption.js +6 -0
  190. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  191. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  192. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  193. package/dist/Selector/types.d.ts +1 -0
  194. package/dist/Selector/types.d.ts.map +1 -1
  195. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  196. package/dist/SideNav/SideNavHeading.js +4 -4
  197. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  198. package/dist/SideNav/SideNavItem.js +3 -3
  199. package/dist/Slider/Slider.d.ts.map +1 -1
  200. package/dist/Slider/Slider.js +7 -7
  201. package/dist/Stack/Stack.d.ts +23 -1
  202. package/dist/Stack/Stack.d.ts.map +1 -1
  203. package/dist/Stack/Stack.js +12 -6
  204. package/dist/Switch/Switch.d.ts.map +1 -1
  205. package/dist/Switch/Switch.js +2 -2
  206. package/dist/TabList/Tab.d.ts.map +1 -1
  207. package/dist/TabList/Tab.js +1 -1
  208. package/dist/TabList/TabMenu.d.ts.map +1 -1
  209. package/dist/TabList/TabMenu.js +3 -3
  210. package/dist/Table/TableRow.js +4 -4
  211. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  212. package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
  213. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  214. package/dist/Table/plugins/filtering/useTableFiltering.js +2 -2
  215. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  216. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +2 -2
  217. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  218. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +2 -2
  219. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  220. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  221. package/dist/Table/plugins/sortable/useTableSortableState.d.ts +5 -3
  222. package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
  223. package/dist/Table/plugins/sortable/useTableSortableState.js +12 -9
  224. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  225. package/dist/Table/plugins/tree/useTableTreeData.js +3 -3
  226. package/dist/TextArea/TextArea.js +1 -1
  227. package/dist/TextInput/TextInput.js +1 -1
  228. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  229. package/dist/Thumbnail/Thumbnail.js +3 -3
  230. package/dist/TimeInput/TimeInput.js +2 -2
  231. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  232. package/dist/Timestamp/Timestamp.js +6 -4
  233. package/dist/Timestamp/formatInstant.d.ts +3 -2
  234. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  235. package/dist/Timestamp/formatInstant.js +8 -8
  236. package/dist/Timestamp/tooltipEntries.d.ts +2 -1
  237. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  238. package/dist/Timestamp/tooltipEntries.js +5 -3
  239. package/dist/Toast/Toast.d.ts +4 -3
  240. package/dist/Toast/Toast.d.ts.map +1 -1
  241. package/dist/Toast/Toast.js +10 -7
  242. package/dist/Token/Token.d.ts.map +1 -1
  243. package/dist/Token/Token.js +6 -6
  244. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  245. package/dist/Tokenizer/Tokenizer.js +1 -1
  246. package/dist/Tooltip/Tooltip.d.ts +16 -3
  247. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  248. package/dist/Tooltip/Tooltip.js +2 -0
  249. package/dist/Tooltip/index.d.ts +1 -1
  250. package/dist/Tooltip/index.d.ts.map +1 -1
  251. package/dist/Tooltip/useTooltip.d.ts +21 -2
  252. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  253. package/dist/Tooltip/useTooltip.js +71 -13
  254. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  255. package/dist/TopNav/TopNavHeading.js +4 -4
  256. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  257. package/dist/TopNav/TopNavItem.js +3 -3
  258. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  259. package/dist/TopNav/TopNavMegaMenu.js +2 -2
  260. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  261. package/dist/TopNav/TopNavMegaMenuItem.js +2 -2
  262. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  263. package/dist/TopNav/TopNavMenu.js +4 -4
  264. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  265. package/dist/TreeList/TreeListItem.js +7 -7
  266. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  267. package/dist/Typeahead/BaseTypeahead.js +2 -2
  268. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  269. package/dist/Typeahead/Typeahead.js +1 -1
  270. package/dist/astryx.css +124 -62
  271. package/dist/hooks/containerReveal.stylex.d.ts.map +1 -1
  272. package/dist/hooks/containerReveal.stylex.js +18 -18
  273. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  274. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  275. package/dist/hooks/scrollbarGutter.js +103 -0
  276. package/dist/hooks/useAutoMediaMode.d.ts +31 -0
  277. package/dist/hooks/useAutoMediaMode.d.ts.map +1 -0
  278. package/dist/hooks/useAutoMediaMode.js +201 -0
  279. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  280. package/dist/hooks/useInputStatusIcon.js +1 -1
  281. package/dist/hooks/useListFocus.d.ts +5 -2
  282. package/dist/hooks/useListFocus.d.ts.map +1 -1
  283. package/dist/hooks/useListFocus.js +12 -6
  284. package/dist/hooks/useScrollLock.d.ts +4 -0
  285. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  286. package/dist/hooks/useScrollLock.js +13 -1
  287. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  288. package/dist/i18n/InternationalizationContext.js +2 -0
  289. package/dist/i18n/index.d.ts +6 -0
  290. package/dist/i18n/index.d.ts.map +1 -1
  291. package/dist/i18n/index.js +6 -0
  292. package/dist/i18n/useCollator.d.ts +12 -0
  293. package/dist/i18n/useCollator.d.ts.map +1 -0
  294. package/dist/i18n/useCollator.js +40 -0
  295. package/dist/i18n/useLocale.d.ts +3 -0
  296. package/dist/i18n/useLocale.d.ts.map +1 -0
  297. package/dist/i18n/useLocale.js +31 -0
  298. package/dist/theme/MediaTheme.d.ts +25 -5
  299. package/dist/theme/MediaTheme.d.ts.map +1 -1
  300. package/dist/theme/MediaTheme.js +31 -6
  301. package/dist/theme/defineTheme.d.ts +5 -0
  302. package/dist/theme/defineTheme.d.ts.map +1 -1
  303. package/dist/theme/defineTheme.js +5 -0
  304. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  305. package/dist/theme/derivedVarRegistry.js +7 -0
  306. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  307. package/dist/theme/generateThemeRules.js +66 -5
  308. package/dist/theme/index.d.ts +1 -1
  309. package/dist/theme/index.d.ts.map +1 -1
  310. package/dist/theme/syntax/index.d.ts +6 -0
  311. package/dist/theme/syntax/index.d.ts.map +1 -1
  312. package/dist/theme/syntax/index.js +7 -2
  313. package/dist/utils/dateParser.d.ts +4 -3
  314. package/dist/utils/dateParser.d.ts.map +1 -1
  315. package/dist/utils/dateParser.js +8 -8
  316. package/dist/utils/index.d.ts +1 -1
  317. package/dist/utils/index.d.ts.map +1 -1
  318. package/dist/utils/index.js +1 -1
  319. package/dist/utils/plainDate.d.ts +5 -2
  320. package/dist/utils/plainDate.d.ts.map +1 -1
  321. package/dist/utils/plainDate.js +20 -4
  322. package/locales/en.json +28 -0
  323. package/locales/pseudo.json +21 -0
  324. package/package.json +3 -3
  325. package/src/Avatar/Avatar.doc.mjs +10 -6
  326. package/src/Avatar/Avatar.test.tsx +219 -1
  327. package/src/Avatar/Avatar.tsx +179 -37
  328. package/src/Avatar/AvatarStatusDot.tsx +30 -4
  329. package/src/Avatar/AvatarStatusLabelContext.ts +47 -0
  330. package/src/AvatarGroup/AvatarGroup.doc.mjs +10 -6
  331. package/src/AvatarGroup/AvatarGroup.test.tsx +62 -0
  332. package/src/AvatarGroup/AvatarGroup.tsx +3 -1
  333. package/src/AvatarGroup/AvatarGroupOverflow.tsx +31 -8
  334. package/src/Banner/Banner.doc.mjs +2 -0
  335. package/src/Blockquote/Blockquote.doc.mjs +30 -7
  336. package/src/Blockquote/Blockquote.test.tsx +34 -3
  337. package/src/Blockquote/Blockquote.tsx +11 -9
  338. package/src/BottomSheet/BottomSheet.doc.mjs +3 -3
  339. package/src/BottomSheet/BottomSheet.test.tsx +24 -0
  340. package/src/BottomSheet/BottomSheetPanel.test.tsx +91 -0
  341. package/src/BottomSheet/BottomSheetPanel.tsx +58 -3
  342. package/src/Breadcrumbs/BreadcrumbItem.tsx +36 -23
  343. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +26 -2
  344. package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -0
  345. package/src/Button/Button.tsx +12 -9
  346. package/src/Calendar/Calendar.tsx +15 -9
  347. package/src/Calendar/hooks/useCalendarNavigation.ts +6 -4
  348. package/src/Calendar/styles.ts +8 -5
  349. package/src/Center/Center.doc.mjs +48 -0
  350. package/src/Center/Center.test.tsx +158 -0
  351. package/src/Center/Center.tsx +50 -9
  352. package/src/Chat/ChatComposer.tsx +11 -5
  353. package/src/Chat/ChatComposerDrawer.tsx +4 -1
  354. package/src/Chat/ChatToolCalls.tsx +13 -4
  355. package/src/Chat/{useChatDictation.test.ts → useChatDictation.test.tsx} +29 -14
  356. package/src/Chat/useChatDictation.ts +1 -1
  357. package/src/Chat/useSpeechRecognition.ts +5 -3
  358. package/src/Chat/useTriggerMenu.tsx +4 -1
  359. package/src/CheckboxInput/CheckboxInput.tsx +5 -2
  360. package/src/Citation/Citation.test.tsx +6 -1
  361. package/src/Citation/Citation.tsx +11 -5
  362. package/src/ClickableCard/ClickableCard.tsx +7 -4
  363. package/src/CodeBlock/CodeBlock.tsx +4 -1
  364. package/src/Collapsible/Collapsible.tsx +5 -2
  365. package/src/CommandPalette/CommandPaletteItem.tsx +6 -3
  366. package/src/ComplexSelector/ComplexSelector.doc.mjs +10 -0
  367. package/src/ComplexSelector/ComplexSelector.tsx +14 -7
  368. package/src/DateInput/DateInput.test.tsx +17 -1
  369. package/src/DateInput/DateInput.tsx +93 -21
  370. package/src/DateInput/DateInputTouch.test.tsx +2582 -0
  371. package/src/DateInput/MonthScroller.tsx +878 -0
  372. package/src/DateInput/MonthYearWheels.tsx +147 -0
  373. package/src/DateInput/TouchDateField.tsx +1223 -0
  374. package/src/DateInput/Wheel.tsx +473 -0
  375. package/src/DateInput/monthGeometry.ts +118 -0
  376. package/src/DateInput/tokens.stylex.ts +99 -0
  377. package/src/DateInput/useOwnScrollGesture.ts +227 -0
  378. package/src/DateInput/usePointerDragScroll.ts +220 -0
  379. package/src/DateInput/useScrollSettle.ts +164 -0
  380. package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
  381. package/src/DateRangeInput/DateRangeInput.tsx +31 -13
  382. package/src/DateTimeInput/DateTimeInput.tsx +25 -9
  383. package/src/Dialog/Dialog.test.tsx +24 -0
  384. package/src/Dialog/Dialog.tsx +3 -0
  385. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -2
  386. package/src/DropdownMenu/DropdownMenuItem.tsx +5 -2
  387. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -2
  388. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -2
  389. package/src/Field/Field.doc.mjs +2 -0
  390. package/src/Field/FieldLabel.tsx +9 -3
  391. package/src/Field/InputClearButton.test.tsx +110 -3
  392. package/src/Field/InputClearButton.tsx +38 -0
  393. package/src/Field/inputStyles.stylex.ts +17 -13
  394. package/src/FileInput/FileInput.tsx +15 -8
  395. package/src/FormLayout/FormLayout.doc.mjs +1 -1
  396. package/src/HoverCard/HoverCard.doc.mjs +18 -0
  397. package/src/HoverCard/HoverCard.test.tsx +189 -0
  398. package/src/HoverCard/HoverCard.tsx +22 -2
  399. package/src/HoverCard/index.ts +1 -0
  400. package/src/HoverCard/useHoverCard.doc.mjs +2 -0
  401. package/src/HoverCard/useHoverCard.tsx +103 -7
  402. package/src/InputGroup/InputGroup.tsx +1 -1
  403. package/src/Item/Item.doc.mjs +1 -0
  404. package/src/Item/Item.test.tsx +50 -0
  405. package/src/Item/Item.tsx +54 -6
  406. package/src/Layer/index.ts +10 -0
  407. package/src/Layer/useLayer.tsx +13 -2
  408. package/src/Layer/useTouchTrigger.test.ts +70 -0
  409. package/src/Layer/useTouchTrigger.ts +366 -0
  410. package/src/Layout/Layout.doc.mjs +18 -0
  411. package/src/Layout/container.stylex.ts +11 -3
  412. package/src/Layout/index.ts +4 -0
  413. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  414. package/src/Layout/padding.stylex.ts +192 -12
  415. package/src/Lightbox/Lightbox.tsx +11 -3
  416. package/src/Link/Link.tsx +9 -6
  417. package/src/MetadataList/MetadataList.tsx +4 -1
  418. package/src/MobileNav/MobileNav.tsx +61 -5
  419. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  420. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  421. package/src/MultiSelector/MultiSelector.test.tsx +1 -1
  422. package/src/MultiSelector/MultiSelector.tsx +26 -10
  423. package/src/NavItem/navItemStyles.stylex.ts +7 -4
  424. package/src/NavMenu/NavHeadingMenuItem.tsx +6 -3
  425. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  426. package/src/NumberInput/NumberInput.test.tsx +138 -0
  427. package/src/NumberInput/NumberInput.tsx +47 -8
  428. package/src/Outline/Outline.tsx +5 -2
  429. package/src/Pagination/Pagination.tsx +5 -2
  430. package/src/Popover/Popover.test.tsx +27 -1
  431. package/src/PowerSearch/PowerSearch.tsx +17 -8
  432. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  433. package/src/PowerSearch/formatFilterValue.test.ts +22 -2
  434. package/src/PowerSearch/formatFilterValue.ts +31 -6
  435. package/src/RadioList/RadioList.doc.mjs +1 -1
  436. package/src/RadioList/RadioList.test.tsx +170 -2
  437. package/src/RadioList/RadioListItem.tsx +88 -53
  438. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  439. package/src/Resizable/ResizeHandle.tsx +25 -7
  440. package/src/Section/Section.doc.mjs +55 -0
  441. package/src/Section/Section.test.tsx +201 -4
  442. package/src/Section/Section.tsx +69 -0
  443. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  444. package/src/SegmentedControl/SegmentedControlItem.tsx +15 -3
  445. package/src/SelectableCard/SelectableCard.tsx +6 -3
  446. package/src/Selector/Selector.doc.mjs +16 -2
  447. package/src/Selector/Selector.test.tsx +525 -1
  448. package/src/Selector/Selector.tsx +180 -25
  449. package/src/Selector/SelectorOption.doc.mjs +7 -0
  450. package/src/Selector/SelectorOption.tsx +21 -0
  451. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  452. package/src/Selector/types.ts +4 -4
  453. package/src/SideNav/SideNavHeading.tsx +14 -5
  454. package/src/SideNav/SideNavItem.tsx +9 -3
  455. package/src/Slider/Slider.tsx +25 -6
  456. package/src/Stack/Stack.doc.mjs +72 -0
  457. package/src/Stack/Stack.test.tsx +156 -0
  458. package/src/Stack/Stack.tsx +50 -8
  459. package/src/Switch/Switch.tsx +5 -2
  460. package/src/TabList/Tab.tsx +4 -1
  461. package/src/TabList/TabMenu.tsx +9 -3
  462. package/src/Table/TableRow.tsx +4 -4
  463. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +6 -2
  464. package/src/Table/plugins/filtering/useTableFiltering.tsx +4 -1
  465. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +10 -3
  466. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +6 -3
  467. package/src/Table/plugins/sortable/useTableSortable.tsx +4 -1
  468. package/src/Table/plugins/sortable/useTableSortableState.test.tsx +34 -0
  469. package/src/Table/plugins/sortable/useTableSortableState.tsx +26 -23
  470. package/src/Table/plugins/tree/useTableTreeData.tsx +10 -4
  471. package/src/TextArea/TextArea.doc.mjs +1 -1
  472. package/src/TextArea/TextArea.tsx +1 -1
  473. package/src/TextInput/TextInput.tsx +1 -1
  474. package/src/Thumbnail/Thumbnail.tsx +9 -3
  475. package/src/TimeInput/TimeInput.tsx +1 -1
  476. package/src/Timestamp/Timestamp.test.tsx +27 -7
  477. package/src/Timestamp/Timestamp.tsx +8 -4
  478. package/src/Timestamp/formatInstant.ts +9 -7
  479. package/src/Timestamp/tooltipEntries.test.ts +11 -6
  480. package/src/Timestamp/tooltipEntries.ts +6 -2
  481. package/src/Toast/Toast.tsx +9 -7
  482. package/src/Token/Token.tsx +14 -5
  483. package/src/Tokenizer/Tokenizer.tsx +4 -1
  484. package/src/Tooltip/Tooltip.doc.mjs +18 -0
  485. package/src/Tooltip/Tooltip.test.tsx +254 -1
  486. package/src/Tooltip/Tooltip.tsx +22 -2
  487. package/src/Tooltip/index.ts +1 -0
  488. package/src/Tooltip/useTooltip.doc.mjs +2 -0
  489. package/src/Tooltip/useTooltip.tsx +99 -21
  490. package/src/TopNav/TopNavHeading.tsx +13 -4
  491. package/src/TopNav/TopNavItem.tsx +6 -3
  492. package/src/TopNav/TopNavMegaMenu.tsx +5 -2
  493. package/src/TopNav/TopNavMegaMenuItem.tsx +5 -2
  494. package/src/TopNav/TopNavMenu.tsx +10 -4
  495. package/src/TreeList/TreeListItem.tsx +22 -7
  496. package/src/Typeahead/BaseTypeahead.tsx +5 -2
  497. package/src/Typeahead/Typeahead.tsx +4 -1
  498. package/src/hooks/containerReveal.stylex.ts +54 -18
  499. package/src/hooks/scrollbarGutter.test.ts +167 -0
  500. package/src/hooks/scrollbarGutter.ts +121 -0
  501. package/src/hooks/useAutoMediaMode.test.ts +109 -0
  502. package/src/hooks/useAutoMediaMode.ts +233 -0
  503. package/src/hooks/useInputStatusIcon.tsx +4 -1
  504. package/src/hooks/useListFocus.doc.mjs +2 -2
  505. package/src/hooks/useListFocus.test.tsx +65 -3
  506. package/src/hooks/useListFocus.ts +15 -7
  507. package/src/hooks/useScrollLock.doc.mjs +4 -4
  508. package/src/hooks/useScrollLock.test.ts +73 -0
  509. package/src/hooks/useScrollLock.ts +14 -0
  510. package/src/i18n/InternationalizationContext.ts +2 -0
  511. package/src/i18n/__tests__/e2e-powersearch.test.tsx +37 -1
  512. package/src/i18n/__tests__/useCollator.test.tsx +115 -0
  513. package/src/i18n/__tests__/useLocale.test.tsx +52 -0
  514. package/src/i18n/index.ts +6 -0
  515. package/src/i18n/useCollator.doc.mjs +84 -0
  516. package/src/i18n/useCollator.ts +44 -0
  517. package/src/i18n/useLocale.doc.mjs +70 -0
  518. package/src/i18n/useLocale.ts +34 -0
  519. package/src/i18n/useTranslator.doc.mjs +1 -1
  520. package/src/reset.css +9 -2
  521. package/src/reset.test.ts +22 -0
  522. package/src/theme/MediaTheme.doc.mjs +23 -4
  523. package/src/theme/MediaTheme.dom.test.tsx +97 -0
  524. package/src/theme/MediaTheme.tsx +42 -7
  525. package/src/theme/defineTheme.test.ts +9 -3
  526. package/src/theme/defineTheme.ts +5 -0
  527. package/src/theme/derivedVarRegistry.test.ts +19 -5
  528. package/src/theme/derivedVarRegistry.ts +4 -0
  529. package/src/theme/generateThemeRules.test.ts +118 -0
  530. package/src/theme/generateThemeRules.ts +83 -5
  531. package/src/theme/index.ts +1 -1
  532. package/src/theme/syntax/index.ts +6 -2
  533. package/src/theme/syntax/serverSafeSyntax.test.ts +68 -0
  534. package/src/utils/dateParser.test.ts +20 -0
  535. package/src/utils/dateParser.ts +14 -7
  536. package/src/utils/index.ts +2 -0
  537. package/src/utils/plainDate.test.ts +6 -0
  538. package/src/utils/plainDate.ts +21 -4
@@ -18,10 +18,8 @@
18
18
  */
19
19
 
20
20
  import {useState, useMemo, useCallback, useRef} from 'react';
21
- import type {
22
- TableSortState,
23
- UseTableSortableConfig,
24
- } from './useTableSortable';
21
+ import type {TableSortState, UseTableSortableConfig} from './useTableSortable';
22
+ import {useCollator} from '../../../i18n/useCollator';
25
23
 
26
24
  // =============================================================================
27
25
  // Comparator Types
@@ -104,14 +102,16 @@ export interface UseTableSortableStateConfig<
104
102
  * two row items. Comparators should sort ascending — the hook flips the
105
103
  * sign for descending.
106
104
  *
107
- * For keys not in this map, the hook falls back to `localeCompare` with
108
- * `{ numeric: true }` on the stringified values.
105
+ * For keys not in this map, the hook falls back to an `Intl.Collator`
106
+ * comparison (`{numeric: true}`) on the stringified values, bound to the
107
+ * active `InternationalizationProvider` locale.
109
108
  *
110
109
  * @example
111
110
  * ```
111
+ * const collator = useCollator({numeric: true});
112
112
  * comparators: {
113
113
  * age: (a, b) => a.age - b.age,
114
- * name: (a, b) => a.name.localeCompare(b.name),
114
+ * name: (a, b) => collator.compare(a.name, b.name),
115
115
  * }
116
116
  * ```
117
117
  */
@@ -164,6 +164,7 @@ function defaultCompare<T extends Record<string, unknown>>(
164
164
  a: T,
165
165
  b: T,
166
166
  sortKey: string,
167
+ collator: Intl.Collator,
167
168
  ): number {
168
169
  const aVal = a[sortKey];
169
170
  const bVal = b[sortKey];
@@ -171,8 +172,10 @@ function defaultCompare<T extends Record<string, unknown>>(
171
172
  // null/undefined/NaN sort to the end. NaN must not reach the numeric fast
172
173
  // path: a NaN comparator result reads as "equal" to Array.sort, which makes
173
174
  // the comparator inconsistent and corrupts the order of the other rows.
174
- const aMissing = aVal == null || (typeof aVal === 'number' && Number.isNaN(aVal));
175
- const bMissing = bVal == null || (typeof bVal === 'number' && Number.isNaN(bVal));
175
+ const aMissing =
176
+ aVal == null || (typeof aVal === 'number' && Number.isNaN(aVal));
177
+ const bMissing =
178
+ bVal == null || (typeof bVal === 'number' && Number.isNaN(bVal));
176
179
  if (aMissing && bMissing) {
177
180
  return 0;
178
181
  }
@@ -188,14 +191,9 @@ function defaultCompare<T extends Record<string, unknown>>(
188
191
  return aVal - bVal;
189
192
  }
190
193
 
191
- // string comparison with numeric collation
192
- return toSortableString(aVal).localeCompare(
193
- toSortableString(bVal),
194
- undefined,
195
- {
196
- numeric: true,
197
- },
198
- );
194
+ // string comparison with numeric collation, bound to the provider locale
195
+ // via useCollator() rather than a raw localeCompare(value, locale) call.
196
+ return collator.compare(toSortableString(aVal), toSortableString(bVal));
199
197
  }
200
198
 
201
199
  // =============================================================================
@@ -208,7 +206,8 @@ function sortData<
208
206
  >(
209
207
  data: T[],
210
208
  sortState: TableSortState<TSortKey>,
211
- comparators?: Partial<Record<TSortKey, TableSortComparator<T>>>,
209
+ comparators: Partial<Record<TSortKey, TableSortComparator<T>>> | undefined,
210
+ collator: Intl.Collator,
212
211
  ): T[] {
213
212
  if (sortState.length === 0) {
214
213
  return data;
@@ -218,7 +217,9 @@ function sortData<
218
217
  for (const entry of sortState) {
219
218
  const {sortKey, direction} = entry;
220
219
  const customCmp = comparators?.[sortKey];
221
- const cmp = customCmp ? customCmp(a, b) : defaultCompare(a, b, sortKey);
220
+ const cmp = customCmp
221
+ ? customCmp(a, b)
222
+ : defaultCompare(a, b, sortKey, collator);
222
223
 
223
224
  if (cmp !== 0) {
224
225
  return direction === 'ascending' ? cmp : -cmp;
@@ -265,6 +266,7 @@ export function useTableSortableState<
265
266
  allowUnsortedState,
266
267
  isMultiSortEnabled,
267
268
  } = config;
269
+ const collator = useCollator({numeric: true});
268
270
 
269
271
  // Internal state (used in uncontrolled mode)
270
272
  const [internalSort, setInternalSort] =
@@ -287,14 +289,15 @@ export function useTableSortableState<
287
289
 
288
290
  // Sorted data — memoized on sort state + data identity
289
291
  const sortedData = useMemo(
290
- () => sortData(data, sort, comparatorsRef.current),
291
- [data, sort],
292
+ () => sortData(data, sort, comparatorsRef.current, collator),
293
+ [data, sort, collator],
292
294
  );
293
295
 
294
296
  // applySort — lets consumers sort arbitrary data with the current state
295
297
  const applySort = useCallback(
296
- (inputData: T[]): T[] => sortData(inputData, sort, comparatorsRef.current),
297
- [sort],
298
+ (inputData: T[]): T[] =>
299
+ sortData(inputData, sort, comparatorsRef.current, collator),
300
+ [sort, collator],
298
301
  );
299
302
 
300
303
  // Config ready for useTableSortable
@@ -242,7 +242,10 @@ const treeStyles = stylex.create({
242
242
  background: 'transparent',
243
243
  border: 'none',
244
244
  borderRadius: radiusVars['--radius-inner'],
245
- cursor: 'pointer',
245
+ cursor: {
246
+ default: 'pointer',
247
+ ':is(:disabled,[aria-disabled="true"])': 'default',
248
+ },
246
249
  color: colorVars['--color-icon-secondary'],
247
250
  transitionProperty: 'color, background-color',
248
251
  transitionDuration: '150ms',
@@ -251,11 +254,11 @@ const treeStyles = stylex.create({
251
254
  // Match IconButton ghost hover: subtle overlay background
252
255
  backgroundImage: {
253
256
  default: null,
254
- ':hover': {
257
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
255
258
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
256
259
  },
257
260
  },
258
- ':hover': {
261
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
259
262
  color: colorVars['--color-icon-primary'],
260
263
  },
261
264
  },
@@ -296,7 +299,10 @@ const treeStyles = stylex.create({
296
299
  },
297
300
  /** Whole-row-click expansion: signal the row is interactive. */
298
301
  clickableRow: {
299
- cursor: 'pointer',
302
+ cursor: {
303
+ default: 'pointer',
304
+ ':is(:disabled,[aria-disabled="true"])': 'default',
305
+ },
300
306
  },
301
307
  });
302
308
 
@@ -105,7 +105,7 @@ export const docs = {
105
105
  name: 'maxLength',
106
106
  type: 'number',
107
107
  description:
108
- 'Maximum number of characters allowed, counted as user-perceived characters an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.',
108
+ 'Maximum number of characters allowed, counted as user-perceived characters: an emoji or flag sequence counts as one. When set, a character counter (current/max) is displayed inside the input container, anchored to the bottom-right beneath the text. Does not enforce the limit natively; when exceeded the counter turns red and shows a warning icon (a non-color cue), and screen-reader users hear the remaining/over-limit count announced. Consumers validating the limit should count with characterCount (exported from the package) so enforcement matches the displayed count.',
109
109
  },
110
110
  {
111
111
  name: 'status',
@@ -108,7 +108,7 @@ const styles = stylex.create({
108
108
  resize: 'vertical',
109
109
  },
110
110
  textareaDisabled: {
111
- cursor: 'not-allowed',
111
+ cursor: 'default',
112
112
  },
113
113
  // Reserve start padding so text clears the start icon.
114
114
  // inline inset + 16px icon (sm) + 8px gap
@@ -71,7 +71,7 @@ const styles = stylex.create({
71
71
  },
72
72
  },
73
73
  inputDisabled: {
74
- cursor: 'not-allowed',
74
+ cursor: 'default',
75
75
  },
76
76
  });
77
77
 
@@ -159,7 +159,10 @@ const styles = stylex.create({
159
159
  color: colorVars['--color-icon-secondary'],
160
160
  },
161
161
  interactive: {
162
- cursor: 'pointer',
162
+ cursor: {
163
+ default: 'pointer',
164
+ ':is(:disabled,[aria-disabled="true"])': 'default',
165
+ },
163
166
  },
164
167
  // Hover/pressed overlay — the exact same treatment as ClickableCard and
165
168
  // SelectableCard. A transparent `::after` tints on hover/press instead of
@@ -183,14 +186,17 @@ const styles = stylex.create({
183
186
  },
184
187
  hoverOnPointer: {
185
188
  '@media (hover: hover)': {
186
- ':hover::after': {
189
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))::after': {
187
190
  backgroundColor: colorVars['--color-overlay-hover'],
188
191
  },
189
192
  },
190
193
  },
191
194
  interactiveButton: {
192
195
  all: 'unset',
193
- cursor: 'pointer',
196
+ cursor: {
197
+ default: 'pointer',
198
+ ':is(:disabled,[aria-disabled="true"])': 'default',
199
+ },
194
200
  display: 'block',
195
201
  width: '100%',
196
202
  height: '100%',
@@ -102,7 +102,7 @@ const styles = stylex.create({
102
102
  },
103
103
  },
104
104
  inputDisabled: {
105
- cursor: 'not-allowed',
105
+ cursor: 'default',
106
106
  },
107
107
  inputInvalid: {
108
108
  color: colorVars['--color-text-secondary'],
@@ -257,6 +257,26 @@ describe('Timestamp', () => {
257
257
 
258
258
  // --- Standard display formats ---
259
259
 
260
+ it('updates absolute output when the provider locale changes', () => {
261
+ const value = '2026-01-25T12:00:00Z';
262
+ const timestamp = (locale: string) => (
263
+ <InternationalizationProvider locale={locale}>
264
+ <Timestamp
265
+ value={value}
266
+ format="date_long"
267
+ hasTooltip={false}
268
+ data-testid="ts"
269
+ />
270
+ </InternationalizationProvider>
271
+ );
272
+
273
+ const {rerender} = render(timestamp('en-US'));
274
+ expect(screen.getByTestId('ts')).toHaveTextContent('January 25, 2026');
275
+
276
+ rerender(timestamp('de-DE'));
277
+ expect(screen.getByTestId('ts')).toHaveTextContent('25. Januar 2026');
278
+ });
279
+
260
280
  it('renders date format', () => {
261
281
  render(
262
282
  <Timestamp value="2026-02-19T17:00:00Z" format="date" data-testid="ts" />,
@@ -441,7 +461,7 @@ describe('Timestamp', () => {
441
461
  );
442
462
 
443
463
  const longTz =
444
- new Intl.DateTimeFormat(undefined, {timeZoneName: 'long'})
464
+ new Intl.DateTimeFormat('en', {timeZoneName: 'long'})
445
465
  .formatToParts(oneHourAgo)
446
466
  .find(p => p.type === 'timeZoneName')?.value ?? '';
447
467
  expect(longTz).not.toBe('');
@@ -462,7 +482,7 @@ describe('Timestamp', () => {
462
482
  );
463
483
 
464
484
  const tzPart = (form: 'short' | 'long') =>
465
- new Intl.DateTimeFormat(undefined, {timeZoneName: form})
485
+ new Intl.DateTimeFormat('en', {timeZoneName: form})
466
486
  .formatToParts(date)
467
487
  .find(p => p.type === 'timeZoneName')?.value ?? '';
468
488
  const text = screen.getByTestId('ts').textContent ?? '';
@@ -673,7 +693,7 @@ describe('Timestamp', () => {
673
693
  // no-break spaces that jest-dom's matcher normalization would break on.
674
694
  const normalize = (s: string) => s.replace(/\s+/g, ' ');
675
695
  const datetime = new Date(el.getAttribute('datetime') ?? '');
676
- const expected = new Intl.DateTimeFormat(undefined, {
696
+ const expected = new Intl.DateTimeFormat('en', {
677
697
  year: 'numeric',
678
698
  month: 'long',
679
699
  day: 'numeric',
@@ -789,7 +809,7 @@ describe('Timestamp', () => {
789
809
  const datetime = new Date(
790
810
  screen.getByTestId('ts').getAttribute('datetime') ?? '',
791
811
  );
792
- const expected = new Intl.DateTimeFormat(undefined, {
812
+ const expected = new Intl.DateTimeFormat('en', {
793
813
  year: 'numeric',
794
814
  month: 'long',
795
815
  day: 'numeric',
@@ -1252,7 +1272,7 @@ describe('Timestamp', () => {
1252
1272
  data-testid="ts"
1253
1273
  />,
1254
1274
  );
1255
- const [line] = formatTooltipLines(new Date(VALUE), [{format}]);
1275
+ const [line] = formatTooltipLines(new Date(VALUE), [{format}], 'en');
1256
1276
  expect(line.value).toBe(screen.getByTestId('ts').textContent);
1257
1277
  },
1258
1278
  );
@@ -1275,10 +1295,10 @@ describe('Timestamp', () => {
1275
1295
  );
1276
1296
  const date = new Date(VALUE);
1277
1297
  const tzPart = (form: 'short' | 'long') =>
1278
- new Intl.DateTimeFormat(undefined, {timeZoneName: form})
1298
+ new Intl.DateTimeFormat('en', {timeZoneName: form})
1279
1299
  .formatToParts(date)
1280
1300
  .find(p => p.type === 'timeZoneName')?.value ?? '';
1281
- const [line] = formatTooltipLines(date, [{format: 'full'}]);
1301
+ const [line] = formatTooltipLines(date, [{format: 'full'}], 'en');
1282
1302
  expect(screen.getByTestId('ts').getAttribute('aria-label')).toBe(
1283
1303
  line.value.replace(tzPart('short'), tzPart('long')),
1284
1304
  );
@@ -23,6 +23,7 @@ import type {TextType, TextSize, TextColor, TextWeight} from '../theme/types';
23
23
  import {mergeProps, mergeRefs} from '../utils';
24
24
  import {useDevWarning} from '../hooks/useDevWarning';
25
25
  import {useTranslator} from '../i18n';
26
+ import {useLocale} from '../i18n/useLocale';
26
27
  import type {BaseProps} from '../BaseProps';
27
28
  import {themeProps} from '../utils/themeProps';
28
29
  import {formatInstant} from './formatInstant';
@@ -419,6 +420,7 @@ export function Timestamp({
419
420
  'data-testid': testId,
420
421
  }: TimestampProps) {
421
422
  const t = useTranslator();
423
+ const locale = useLocale();
422
424
  const timeRef = useRef<HTMLTimeElement>(null);
423
425
  const [now, setNow] = useState(() => new Date());
424
426
 
@@ -448,16 +450,18 @@ export function Timestamp({
448
450
  : effectiveFormat === 'relative_short'
449
451
  ? getRelativeTimeShortString(date, now)
450
452
  : isAbsoluteFormat(effectiveFormat)
451
- ? formatInstant(date, effectiveFormat, {isTimezoneShown})
453
+ ? formatInstant(date, effectiveFormat, locale, {isTimezoneShown})
452
454
  : '';
453
455
 
454
456
  // Full absolute text for the tooltip (visible — keeps the compact timezone
455
457
  // abbreviation) and for the AT-facing aria-label, which spells the timezone
456
458
  // out in full: abbreviations like "PST" or "GMT+2" are unexpanded
457
459
  // abbreviations to a screen-reader user (WCAG 3.1.4).
458
- const fullAbsoluteText = isValidDate ? formatInstant(date, 'full') : '';
460
+ const fullAbsoluteText = isValidDate
461
+ ? formatInstant(date, 'full', locale)
462
+ : '';
459
463
  const ariaLabelText = isValidDate
460
- ? formatInstant(date, 'full', {timeZoneNameStyle: 'long'})
464
+ ? formatInstant(date, 'full', locale, {timeZoneNameStyle: 'long'})
461
465
  : '';
462
466
 
463
467
  // Live updates
@@ -506,7 +510,7 @@ export function Timestamp({
506
510
  const lines: ReadonlyArray<TimestampTooltipLine> =
507
511
  entries === undefined
508
512
  ? [{value: fullAbsoluteText, isCopyable: true}]
509
- : formatTooltipLines(date, entries);
513
+ : formatTooltipLines(date, entries, locale);
510
514
 
511
515
  const timestampProps = mergeProps(
512
516
  themeProps('timestamp', {format: effectiveFormat}),
@@ -30,6 +30,7 @@
30
30
  */
31
31
 
32
32
  import {SHARED_DATE_FORMAT_OPTIONS, getTimeZoneParts} from '../utils/plainDate';
33
+ import type {Locale} from '../i18n/types';
33
34
  import type {TimestampFormat} from './Timestamp';
34
35
 
35
36
  // =============================================================================
@@ -159,12 +160,13 @@ function getWallClock(date: Date, timeZone: string | undefined): WallClock {
159
160
  /**
160
161
  * Renders one instant in one absolute format.
161
162
  *
162
- * Pure: the same arguments always produce the same string for a given host
163
+ * Pure: the same arguments always produce the same string for the requested
163
164
  * locale (and, when no `timeZone` is given, host zone).
164
165
  */
165
166
  export function formatInstant(
166
167
  date: Date,
167
168
  format: InstantFormat,
169
+ locale: Locale,
168
170
  {
169
171
  timeZone,
170
172
  isTimezoneShown = false,
@@ -176,39 +178,39 @@ export function formatInstant(
176
178
 
177
179
  switch (format) {
178
180
  case 'full':
179
- return new Intl.DateTimeFormat(undefined, {
181
+ return new Intl.DateTimeFormat(locale, {
180
182
  ...FULL_OPTIONS,
181
183
  timeZoneName: timeZoneNameStyle,
182
184
  ...zone,
183
185
  }).format(date);
184
186
 
185
187
  case 'date':
186
- return new Intl.DateTimeFormat(undefined, {
188
+ return new Intl.DateTimeFormat(locale, {
187
189
  ...SHARED_DATE_FORMAT_OPTIONS.date,
188
190
  ...zone,
189
191
  }).format(date);
190
192
 
191
193
  case 'date_long':
192
- return new Intl.DateTimeFormat(undefined, {
194
+ return new Intl.DateTimeFormat(locale, {
193
195
  ...SHARED_DATE_FORMAT_OPTIONS.date_long,
194
196
  ...zone,
195
197
  }).format(date);
196
198
 
197
199
  case 'date_weekday':
198
- return new Intl.DateTimeFormat(undefined, {
200
+ return new Intl.DateTimeFormat(locale, {
199
201
  ...SHARED_DATE_FORMAT_OPTIONS.date_weekday,
200
202
  ...zone,
201
203
  }).format(date);
202
204
 
203
205
  case 'date_time':
204
- return new Intl.DateTimeFormat(undefined, {
206
+ return new Intl.DateTimeFormat(locale, {
205
207
  ...DATE_TIME_OPTIONS,
206
208
  ...zoneName,
207
209
  ...zone,
208
210
  }).format(date);
209
211
 
210
212
  case 'time':
211
- return new Intl.DateTimeFormat(undefined, {
213
+ return new Intl.DateTimeFormat(locale, {
212
214
  ...TIME_OPTIONS,
213
215
  ...zoneName,
214
216
  ...zone,
@@ -16,12 +16,17 @@
16
16
 
17
17
  import {describe, it, expect, vi} from 'vitest';
18
18
  import {SHARED_DATE_FORMAT_OPTIONS} from '../utils/plainDate';
19
- import {formatTooltipLines} from './tooltipEntries';
19
+ import {formatTooltipLines as formatTooltipLinesForLocale} from './tooltipEntries';
20
+
21
+ const formatTooltipLines = (
22
+ date: Parameters<typeof formatTooltipLinesForLocale>[0],
23
+ entries: Parameters<typeof formatTooltipLinesForLocale>[1],
24
+ ) => formatTooltipLinesForLocale(date, entries, 'en-US');
20
25
 
21
26
  /** 2026-02-19T17:00:00Z — chosen so several zones land on different dates. */
22
27
  const INSTANT = new Date('2026-02-19T17:00:00Z');
23
28
 
24
- const LOCAL_ZONE = Intl.DateTimeFormat().resolvedOptions().timeZone;
29
+ const LOCAL_ZONE = Intl.DateTimeFormat('en-US').resolvedOptions().timeZone;
25
30
 
26
31
  describe('formatTooltipLines', () => {
27
32
  // --- Explicit zones: exact, locale-free, TZ-agnostic ---
@@ -86,7 +91,7 @@ describe('formatTooltipLines', () => {
86
91
  for (const timezoneID of ['UTC', 'Asia/Tokyo']) {
87
92
  const [line] = formatTooltipLines(INSTANT, [{timezoneID, format}]);
88
93
  expect(line.value).toBe(
89
- new Intl.DateTimeFormat(undefined, {
94
+ new Intl.DateTimeFormat('en-US', {
90
95
  ...SHARED_DATE_FORMAT_OPTIONS[format],
91
96
  timeZone: timezoneID,
92
97
  }).format(INSTANT),
@@ -208,7 +213,7 @@ describe('formatTooltipLines', () => {
208
213
  {format: 'date_time'},
209
214
  {format: 'system_date_time'},
210
215
  ]);
211
- const localName = new Intl.DateTimeFormat(undefined, {
216
+ const localName = new Intl.DateTimeFormat('en-US', {
212
217
  timeZoneName: 'short',
213
218
  })
214
219
  .formatToParts(INSTANT)
@@ -230,7 +235,7 @@ describe('formatTooltipLines', () => {
230
235
  // aria-describedby, and that element's accessible name is the LOCAL
231
236
  // absolute time. A lone foreign-zone line with no marker is therefore
232
237
  // announced right after a local time, with nothing to say it is not one.
233
- const zoneName = new Intl.DateTimeFormat(undefined, {
238
+ const zoneName = new Intl.DateTimeFormat('en-US', {
234
239
  timeZone: 'Asia/Tokyo',
235
240
  timeZoneName: 'short',
236
241
  })
@@ -248,7 +253,7 @@ describe('formatTooltipLines', () => {
248
253
  // The consumer never named a zone, so there is nothing to disambiguate
249
254
  // against — this must stay as bare as the visible text is by default.
250
255
  const [line] = formatTooltipLines(INSTANT, [{format: 'date_time'}]);
251
- const localName = new Intl.DateTimeFormat(undefined, {
256
+ const localName = new Intl.DateTimeFormat('en-US', {
252
257
  timeZoneName: 'short',
253
258
  })
254
259
  .formatToParts(INSTANT)
@@ -24,6 +24,7 @@
24
24
  import {devWarn} from '../utils/devWarning';
25
25
  import {formatInstant} from './formatInstant';
26
26
  import type {InstantFormat} from './formatInstant';
27
+ import type {Locale} from '../i18n/types';
27
28
 
28
29
  // =============================================================================
29
30
  // Types
@@ -130,7 +131,9 @@ function resolveTimezoneID(timezoneID: string | undefined): string | undefined {
130
131
  // degrade to the viewer's zone and say so, mirroring how an unparseable
131
132
  // `value` is handled in Timestamp.tsx.
132
133
  try {
133
- new Intl.DateTimeFormat(undefined, {timeZone: timezoneID});
134
+ // Locale does not affect time-zone identifier validity; pin one so this
135
+ // validation path stays explicit and deterministic.
136
+ new Intl.DateTimeFormat('en-US', {timeZone: timezoneID});
134
137
  } catch {
135
138
  if (!warnedTimezoneIDs.has(timezoneID)) {
136
139
  warnedTimezoneIDs.add(timezoneID);
@@ -202,6 +205,7 @@ function shouldShowZoneName(
202
205
  export function formatTooltipLines(
203
206
  date: Date,
204
207
  entries: ReadonlyArray<TimestampTooltipEntry>,
208
+ locale: Locale,
205
209
  ): ReadonlyArray<TimestampTooltipLine> {
206
210
  const resolved = entries.map(entry => resolveTimezoneID(entry.timezoneID));
207
211
  const hasMultipleZones = new Set(resolved.map(zoneKey)).size > 1;
@@ -213,7 +217,7 @@ export function formatTooltipLines(
213
217
  return {
214
218
  ...(entry.label === undefined ? {} : {label: entry.label}),
215
219
  isCopyable: entry.isCopyable ?? false,
216
- value: formatInstant(date, format, {
220
+ value: formatInstant(date, format, locale, {
217
221
  timeZone,
218
222
  isTimezoneShown: shouldShowZoneName(
219
223
  format,
@@ -92,9 +92,10 @@ export interface ToastProps {
92
92
  * Individual toast notification.
93
93
  *
94
94
  * Renders with inverted surface colors for the default variant,
95
- * and error-inverted for the error variant. Uses MediaTheme
96
- * to set the correct token context for children. Pauses auto-dismiss
97
- * on hover and focus.
95
+ * and error-inverted for the error variant. Applies MediaTheme for that
96
+ * surface, unless the painted colors make the chosen side unreadable —
97
+ * a theme is free to define an "inverted" background that is not.
98
+ * Pauses auto-dismiss on hover and focus.
98
99
  *
99
100
  * @example
100
101
  * ```
@@ -196,10 +197,11 @@ export function Toast({
196
197
  }, [onDismiss]);
197
198
 
198
199
  const isError = type === 'error';
199
- // Determine media mode: inverted surface is always dark in light mode,
200
- // always light in dark mode. Error toast is always on a dark surface.
200
+ // The surface is *usually* dark in light mode and light in dark mode, but a
201
+ // theme can define --color-background-inverted as anything so the mode is
202
+ // measured, not assumed. This is only the pre-measurement fallback.
201
203
  const {mode} = useTheme();
202
- const mediaMode = isError || mode === 'light' ? 'dark' : 'light';
204
+ const fallbackMediaMode = isError || mode === 'light' ? 'dark' : 'light';
203
205
 
204
206
  return (
205
207
  <div
@@ -218,7 +220,7 @@ export function Toast({
218
220
  isExiting && styles.exiting,
219
221
  ),
220
222
  )}>
221
- <MediaTheme mode={mediaMode}>
223
+ <MediaTheme mode="auto" fallback={fallbackMediaMode}>
222
224
  <div {...stylex.props(styles.inner)}>
223
225
  <div {...stylex.props(styles.content)}>{body}</div>
224
226
 
@@ -136,20 +136,23 @@ const styles = stylex.create({
136
136
  minWidth: 0,
137
137
  },
138
138
  interactive: {
139
- cursor: 'pointer',
139
+ cursor: {
140
+ default: 'pointer',
141
+ ':is(:disabled,[aria-disabled="true"])': 'default',
142
+ },
140
143
  transitionProperty: 'background-image',
141
144
  transitionDuration: durationVars['--duration-fast'],
142
145
  transitionTimingFunction: easeVars['--ease-standard'],
143
146
  backgroundImage: {
144
147
  default: null,
145
- ':hover': {
148
+ ':hover:where(:not(:disabled,[aria-disabled="true"]))': {
146
149
  '@media (hover: hover)': `linear-gradient(${colorVars['--color-overlay-hover']}, ${colorVars['--color-overlay-hover']})`,
147
150
  },
148
151
  ':active': `linear-gradient(${colorVars['--color-overlay-pressed']}, ${colorVars['--color-overlay-pressed']})`,
149
152
  },
150
153
  },
151
154
  disabled: {
152
- cursor: 'not-allowed',
155
+ cursor: 'default',
153
156
  opacity: 0.5,
154
157
  pointerEvents: 'none' as const,
155
158
  },
@@ -166,7 +169,10 @@ const styles = stylex.create({
166
169
  },
167
170
  invisibleButton: {
168
171
  all: 'unset',
169
- cursor: 'inherit',
172
+ cursor: {
173
+ default: 'inherit',
174
+ ':is(:disabled,[aria-disabled="true"])': 'default',
175
+ },
170
176
  font: 'inherit',
171
177
  color: 'inherit',
172
178
  outline: 'none',
@@ -181,7 +187,10 @@ const styles = stylex.create({
181
187
  position: 'relative',
182
188
  padding: 0,
183
189
  marginInlineEnd: `calc(-1 * ${spacingVars['--spacing-1']})`,
184
- cursor: 'pointer',
190
+ cursor: {
191
+ default: 'pointer',
192
+ ':is(:disabled,[aria-disabled="true"])': 'default',
193
+ },
185
194
  borderRadius: radiusVars['--radius-full'],
186
195
  width: '16px',
187
196
  height: '16px',
@@ -224,7 +224,10 @@ const styles = stylex.create({
224
224
  position: 'relative',
225
225
  flexWrap: 'wrap',
226
226
  gap: spacingVars['--spacing-1'],
227
- cursor: 'text',
227
+ cursor: {
228
+ default: 'text',
229
+ ':is(:disabled,[aria-disabled="true"])': 'default',
230
+ },
228
231
  height: 'auto',
229
232
  },
230
233
  wrapperWithTokens: {