@astryxdesign/core 0.4.7 → 0.5.0-canary.055e75f

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 (597) hide show
  1. package/CHANGELOG.md +161 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  3. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  4. package/dist/AlertDialog/AlertDialog.js +45 -20
  5. package/dist/AppShell/AppShell.d.ts.map +1 -1
  6. package/dist/AppShell/AppShell.js +3 -2
  7. package/dist/AspectRatio/AspectRatio.d.ts +24 -0
  8. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  9. package/dist/AspectRatio/AspectRatio.js +23 -4
  10. package/dist/Avatar/Avatar.d.ts +25 -1
  11. package/dist/Avatar/Avatar.d.ts.map +1 -1
  12. package/dist/Avatar/Avatar.js +58 -19
  13. package/dist/Avatar/index.d.ts +2 -2
  14. package/dist/Avatar/index.d.ts.map +1 -1
  15. package/dist/Avatar/index.js +1 -1
  16. package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
  17. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  18. package/dist/AvatarGroup/AvatarGroup.js +8 -4
  19. package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
  20. package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
  21. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  22. package/dist/AvatarGroup/AvatarGroupOverflow.js +10 -6
  23. package/dist/Banner/Banner.d.ts +40 -15
  24. package/dist/Banner/Banner.d.ts.map +1 -1
  25. package/dist/Banner/Banner.js +51 -18
  26. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  27. package/dist/BottomSheet/BottomSheet.js +17 -4
  28. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  29. package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
  30. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  31. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
  32. package/dist/Button/Button.d.ts.map +1 -1
  33. package/dist/Button/Button.js +11 -6
  34. package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
  35. package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
  36. package/dist/ButtonGroup/ButtonGroup.js +26 -7
  37. package/dist/Calendar/Calendar.d.ts +3 -1
  38. package/dist/Calendar/Calendar.d.ts.map +1 -1
  39. package/dist/Calendar/Calendar.js +14 -15
  40. package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
  41. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
  42. package/dist/Calendar/getInitialFocusDate.js +62 -0
  43. package/dist/Calendar/styles.d.ts +5 -14
  44. package/dist/Calendar/styles.d.ts.map +1 -1
  45. package/dist/Calendar/styles.js +15 -15
  46. package/dist/Card/Card.d.ts +6 -9
  47. package/dist/Card/Card.d.ts.map +1 -1
  48. package/dist/Card/Card.js +6 -6
  49. package/dist/Carousel/Carousel.d.ts.map +1 -1
  50. package/dist/Carousel/Carousel.js +3 -3
  51. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  52. package/dist/Chat/ChatComposerInput.js +2 -3
  53. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  54. package/dist/Chat/ChatLayout.js +3 -3
  55. package/dist/Chat/ChatMessageList.d.ts +22 -3
  56. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  57. package/dist/Chat/ChatMessageList.js +6 -3
  58. package/dist/Chat/ChatTokenizedText.d.ts +2 -0
  59. package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
  60. package/dist/Chat/ChatTokenizedText.js +11 -6
  61. package/dist/Chat/useChatComposerTokens.js +1 -1
  62. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  63. package/dist/CheckboxInput/CheckboxInput.js +10 -3
  64. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  65. package/dist/ClickableCard/ClickableCard.js +3 -3
  66. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  67. package/dist/CodeBlock/CodeBlock.js +15 -4
  68. package/dist/CodeBlock/highlightRanges.js +1 -1
  69. package/dist/CodeBlock/highlightStyles.js +13 -13
  70. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  71. package/dist/CommandPalette/CommandPaletteInput.js +3 -2
  72. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  73. package/dist/CommandPalette/CommandPaletteItem.js +3 -2
  74. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  75. package/dist/ContextMenu/ContextMenu.js +4 -3
  76. package/dist/DateInput/DateInput.d.ts +43 -0
  77. package/dist/DateInput/DateInput.d.ts.map +1 -1
  78. package/dist/DateInput/DateInput.js +22 -2
  79. package/dist/DateInput/NativeDateField.d.ts +10 -0
  80. package/dist/DateInput/NativeDateField.d.ts.map +1 -0
  81. package/dist/DateInput/NativeDateField.js +494 -0
  82. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  83. package/dist/DateInput/TouchDateField.js +82 -23
  84. package/dist/DateInput/index.d.ts +1 -1
  85. package/dist/DateInput/index.d.ts.map +1 -1
  86. package/dist/DateInput/nativeDateSegments.d.ts +22 -0
  87. package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
  88. package/dist/DateInput/nativeDateSegments.js +111 -0
  89. package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
  90. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  91. package/dist/DateTimeInput/DateTimeInput.js +406 -12
  92. package/dist/DateTimeInput/index.d.ts +1 -1
  93. package/dist/DateTimeInput/index.d.ts.map +1 -1
  94. package/dist/Dialog/Dialog.d.ts +21 -1
  95. package/dist/Dialog/Dialog.d.ts.map +1 -1
  96. package/dist/Dialog/Dialog.js +110 -58
  97. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  98. package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
  99. package/dist/Field/FieldLabel.d.ts.map +1 -1
  100. package/dist/Field/FieldLabel.js +9 -1
  101. package/dist/FileInput/FileInput.d.ts.map +1 -1
  102. package/dist/FileInput/FileInput.js +3 -2
  103. package/dist/Heading/Heading.d.ts.map +1 -1
  104. package/dist/Heading/Heading.js +6 -2
  105. package/dist/HoverCard/HoverCard.d.ts +6 -0
  106. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  107. package/dist/HoverCard/HoverCard.js +104 -3
  108. package/dist/HoverCard/useHoverCard.d.ts +19 -2
  109. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  110. package/dist/HoverCard/useHoverCard.js +74 -26
  111. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  112. package/dist/Indicator/CheckboxIndicator.js +6 -2
  113. package/dist/Item/Item.d.ts.map +1 -1
  114. package/dist/Item/Item.js +4 -2
  115. package/dist/Kbd/Kbd.d.ts.map +1 -1
  116. package/dist/Kbd/Kbd.js +2 -19
  117. package/dist/Layer/LayerDepthContext.d.ts +52 -0
  118. package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
  119. package/dist/Layer/LayerDepthContext.js +66 -0
  120. package/dist/Layer/index.d.ts +3 -0
  121. package/dist/Layer/index.d.ts.map +1 -1
  122. package/dist/Layer/index.js +4 -0
  123. package/dist/Layer/layerStack.d.ts +98 -0
  124. package/dist/Layer/layerStack.d.ts.map +1 -0
  125. package/dist/Layer/layerStack.js +306 -0
  126. package/dist/Layer/useLayerDismissal.d.ts +93 -0
  127. package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
  128. package/dist/Layer/useLayerDismissal.js +91 -0
  129. package/dist/Lightbox/Lightbox.d.ts +1 -0
  130. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  131. package/dist/Lightbox/Lightbox.js +103 -81
  132. package/dist/Markdown/Markdown.d.ts.map +1 -1
  133. package/dist/Markdown/Markdown.js +9 -4
  134. package/dist/Markdown/index.d.ts +1 -1
  135. package/dist/Markdown/index.d.ts.map +1 -1
  136. package/dist/Markdown/parser.d.ts +38 -1
  137. package/dist/Markdown/parser.d.ts.map +1 -1
  138. package/dist/Markdown/parser.js +182 -32
  139. package/dist/MobileNav/MobileNav.d.ts +6 -1
  140. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  141. package/dist/MobileNav/MobileNav.js +61 -36
  142. package/dist/MultiSelector/MultiSelector.d.ts +32 -1
  143. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  144. package/dist/MultiSelector/MultiSelector.js +63 -11
  145. package/dist/MultiSelector/index.d.ts +1 -1
  146. package/dist/MultiSelector/index.d.ts.map +1 -1
  147. package/dist/NavIcon/NavIcon.d.ts.map +1 -1
  148. package/dist/NavIcon/NavIcon.js +5 -1
  149. package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
  150. package/dist/NavMenu/NavHeadingMenu.js +3 -2
  151. package/dist/NumberInput/NumberInput.d.ts +6 -1
  152. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  153. package/dist/NumberInput/NumberInput.js +54 -104
  154. package/dist/NumberInput/numberInputCommit.d.ts +34 -0
  155. package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
  156. package/dist/NumberInput/numberInputCommit.js +71 -0
  157. package/dist/NumberInput/numberParser.d.ts +64 -0
  158. package/dist/NumberInput/numberParser.d.ts.map +1 -0
  159. package/dist/NumberInput/numberParser.js +350 -0
  160. package/dist/Outline/Outline.d.ts.map +1 -1
  161. package/dist/Outline/Outline.js +3 -2
  162. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  163. package/dist/OverflowList/OverflowList.js +3 -2
  164. package/dist/Overlay/Overlay.d.ts.map +1 -1
  165. package/dist/Overlay/Overlay.js +3 -2
  166. package/dist/Popover/usePopover.d.ts.map +1 -1
  167. package/dist/Popover/usePopover.js +20 -17
  168. package/dist/PowerSearch/PowerSearch.d.ts +8 -2
  169. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearch.js +19 -6
  171. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
  172. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  173. package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
  174. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
  175. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  176. package/dist/PowerSearch/PowerSearchValueEditor.js +110 -27
  177. package/dist/PowerSearch/types.d.ts +2 -0
  178. package/dist/PowerSearch/types.d.ts.map +1 -1
  179. package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
  180. package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
  181. package/dist/PowerSearch/usePowerSearchSource.js +14 -5
  182. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  183. package/dist/ProgressBar/ProgressBar.js +18 -5
  184. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  185. package/dist/Resizable/ResizeHandle.js +3 -2
  186. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  187. package/dist/SegmentedControl/SegmentedControl.js +3 -2
  188. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  189. package/dist/SelectableCard/SelectableCard.js +3 -3
  190. package/dist/Selector/Selector.d.ts +17 -0
  191. package/dist/Selector/Selector.d.ts.map +1 -1
  192. package/dist/Selector/Selector.js +81 -14
  193. package/dist/SideNav/SideNav.d.ts.map +1 -1
  194. package/dist/SideNav/SideNav.js +4 -3
  195. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  196. package/dist/SideNav/SideNavHeading.js +8 -7
  197. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  198. package/dist/SideNav/SideNavItem.js +4 -3
  199. package/dist/Slider/Slider.d.ts.map +1 -1
  200. package/dist/Slider/Slider.js +37 -5
  201. package/dist/Spinner/Spinner.d.ts +3 -3
  202. package/dist/Spinner/Spinner.d.ts.map +1 -1
  203. package/dist/Spinner/Spinner.js +130 -78
  204. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  205. package/dist/StatusDot/StatusDot.js +6 -1
  206. package/dist/Stepper/Step.d.ts +140 -0
  207. package/dist/Stepper/Step.d.ts.map +1 -0
  208. package/dist/Stepper/Step.js +1045 -0
  209. package/dist/Stepper/StepStatus.d.ts +24 -0
  210. package/dist/Stepper/StepStatus.d.ts.map +1 -0
  211. package/dist/Stepper/StepStatus.js +1 -0
  212. package/dist/Stepper/Stepper.d.ts +93 -0
  213. package/dist/Stepper/Stepper.d.ts.map +1 -0
  214. package/dist/Stepper/Stepper.js +184 -0
  215. package/dist/Stepper/StepperContext.d.ts +41 -0
  216. package/dist/Stepper/StepperContext.d.ts.map +1 -0
  217. package/dist/Stepper/StepperContext.js +34 -0
  218. package/dist/Stepper/index.d.ts +8 -0
  219. package/dist/Stepper/index.d.ts.map +1 -0
  220. package/dist/Stepper/index.js +7 -0
  221. package/dist/Stepper/stepper.stylex.d.ts +15 -0
  222. package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
  223. package/dist/Stepper/stepper.stylex.js +20 -0
  224. package/dist/Switch/Switch.d.ts.map +1 -1
  225. package/dist/Switch/Switch.js +8 -3
  226. package/dist/TabList/Tab.d.ts +15 -2
  227. package/dist/TabList/Tab.d.ts.map +1 -1
  228. package/dist/TabList/Tab.js +32 -7
  229. package/dist/TabList/TabList.d.ts +46 -7
  230. package/dist/TabList/TabList.d.ts.map +1 -1
  231. package/dist/TabList/TabList.js +353 -23
  232. package/dist/TabList/TabListContext.d.ts +11 -1
  233. package/dist/TabList/TabListContext.d.ts.map +1 -1
  234. package/dist/TabList/TabListContext.js +11 -2
  235. package/dist/TabList/TabMenu.d.ts.map +1 -1
  236. package/dist/TabList/TabMenu.js +3 -2
  237. package/dist/TabList/index.d.ts +2 -2
  238. package/dist/TabList/index.d.ts.map +1 -1
  239. package/dist/Table/BaseTable.d.ts.map +1 -1
  240. package/dist/Table/BaseTable.js +10 -2
  241. package/dist/Table/Table.d.ts.map +1 -1
  242. package/dist/Table/Table.js +3 -6
  243. package/dist/Table/TableRow.d.ts +16 -5
  244. package/dist/Table/TableRow.d.ts.map +1 -1
  245. package/dist/Table/TableRow.js +16 -5
  246. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  247. package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
  248. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  249. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
  250. package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
  251. package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
  252. package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
  253. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  254. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  255. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  256. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
  257. package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
  258. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  259. package/dist/Table/plugins/selection/useTableSelection.js +19 -5
  260. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  261. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
  262. package/dist/Table/types.d.ts +22 -4
  263. package/dist/Table/types.d.ts.map +1 -1
  264. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  265. package/dist/Table/useBaseTablePlugins.js +5 -0
  266. package/dist/Text/Text.d.ts.map +1 -1
  267. package/dist/Text/Text.js +6 -2
  268. package/dist/TextArea/TextArea.d.ts.map +1 -1
  269. package/dist/TextArea/TextArea.js +9 -3
  270. package/dist/TextInput/TextInput.d.ts.map +1 -1
  271. package/dist/TextInput/TextInput.js +3 -2
  272. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  273. package/dist/TimeInput/TimeInput.js +3 -2
  274. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  275. package/dist/Timestamp/Timestamp.js +5 -3
  276. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  277. package/dist/Toast/ToastViewport.js +27 -8
  278. package/dist/Token/TokenLink.d.ts.map +1 -1
  279. package/dist/Token/TokenLink.js +2 -2
  280. package/dist/Tokenizer/Tokenizer.d.ts +3 -1
  281. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  282. package/dist/Tokenizer/Tokenizer.js +2 -0
  283. package/dist/Tooltip/Tooltip.d.ts +5 -0
  284. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  285. package/dist/Tooltip/useTooltip.d.ts +5 -0
  286. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  287. package/dist/Tooltip/useTooltip.js +39 -24
  288. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  289. package/dist/TopNav/TopNavHeading.js +5 -4
  290. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  291. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  292. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  293. package/dist/TopNav/TopNavMenu.js +4 -3
  294. package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
  295. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  296. package/dist/Typeahead/BaseTypeahead.js +68 -29
  297. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  298. package/dist/Typeahead/Typeahead.js +3 -2
  299. package/dist/astryx.css +98 -7
  300. package/dist/hooks/index.d.ts +1 -0
  301. package/dist/hooks/index.d.ts.map +1 -1
  302. package/dist/hooks/index.js +1 -0
  303. package/dist/hooks/useFocusTrap.d.ts +7 -4
  304. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  305. package/dist/hooks/useFocusTrap.js +60 -95
  306. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  307. package/dist/hooks/useHotkeys.js +3 -18
  308. package/dist/hooks/useMergedRefs.d.ts +18 -0
  309. package/dist/hooks/useMergedRefs.d.ts.map +1 -0
  310. package/dist/hooks/useMergedRefs.js +25 -0
  311. package/dist/index.d.ts +1 -0
  312. package/dist/index.d.ts.map +1 -1
  313. package/dist/index.js +1 -0
  314. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  315. package/dist/theme/derivedVarRegistry.js +24 -4
  316. package/dist/theme/syntax/tokens.d.ts +1 -1
  317. package/dist/theme/syntax/tokens.d.ts.map +1 -1
  318. package/dist/theme/syntax/tokens.js +5 -2
  319. package/dist/utils/groupItems.d.ts +5 -1
  320. package/dist/utils/groupItems.d.ts.map +1 -1
  321. package/dist/utils/groupItems.js +9 -9
  322. package/dist/utils/index.d.ts +1 -1
  323. package/dist/utils/index.d.ts.map +1 -1
  324. package/dist/utils/isApplePlatform.d.ts +18 -0
  325. package/dist/utils/isApplePlatform.d.ts.map +1 -0
  326. package/dist/utils/isApplePlatform.js +37 -0
  327. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  328. package/dist/utils/sharedResizeObserver.js +10 -1
  329. package/dist/utils/timeParser.d.ts +1 -1
  330. package/dist/utils/timeParser.d.ts.map +1 -1
  331. package/dist/utils/timeParser.js +26 -12
  332. package/locales/en.json +154 -10
  333. package/locales/pseudo.json +108 -0
  334. package/package.json +8 -3
  335. package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
  336. package/src/AlertDialog/AlertDialog.test.tsx +211 -2
  337. package/src/AlertDialog/AlertDialog.tsx +62 -20
  338. package/src/AppShell/AppShell.tsx +3 -2
  339. package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
  340. package/src/AspectRatio/AspectRatio.test.tsx +57 -10
  341. package/src/AspectRatio/AspectRatio.tsx +40 -1
  342. package/src/Avatar/Avatar.doc.mjs +14 -3
  343. package/src/Avatar/Avatar.test.tsx +97 -0
  344. package/src/Avatar/Avatar.tsx +125 -52
  345. package/src/Avatar/index.ts +2 -2
  346. package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
  347. package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
  348. package/src/AvatarGroup/AvatarGroup.tsx +15 -6
  349. package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
  350. package/src/AvatarGroup/AvatarGroupOverflow.tsx +10 -4
  351. package/src/Banner/Banner.doc.mjs +13 -11
  352. package/src/Banner/Banner.test.tsx +102 -15
  353. package/src/Banner/Banner.tsx +72 -25
  354. package/src/BottomSheet/BottomSheet.test.tsx +123 -0
  355. package/src/BottomSheet/BottomSheet.tsx +17 -4
  356. package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
  357. package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
  358. package/src/Button/Button.doc.mjs +24 -1
  359. package/src/Button/Button.test.tsx +32 -4
  360. package/src/Button/Button.tsx +12 -5
  361. package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
  362. package/src/ButtonGroup/ButtonGroup.test.tsx +404 -1
  363. package/src/ButtonGroup/ButtonGroup.tsx +23 -5
  364. package/src/Calendar/Calendar.doc.mjs +4 -3
  365. package/src/Calendar/Calendar.test.tsx +103 -0
  366. package/src/Calendar/Calendar.tsx +19 -16
  367. package/src/Calendar/getInitialFocusDate.test.ts +94 -0
  368. package/src/Calendar/getInitialFocusDate.ts +93 -0
  369. package/src/Calendar/styles.ts +49 -31
  370. package/src/Card/Card.doc.mjs +10 -7
  371. package/src/Card/Card.test.tsx +44 -19
  372. package/src/Card/Card.tsx +12 -32
  373. package/src/Carousel/Carousel.tsx +3 -2
  374. package/src/Chat/ChatComposerInput.tsx +5 -1
  375. package/src/Chat/ChatLayout.tsx +3 -2
  376. package/src/Chat/ChatMessageList.doc.mjs +9 -1
  377. package/src/Chat/ChatMessageList.test.tsx +46 -0
  378. package/src/Chat/ChatMessageList.tsx +28 -4
  379. package/src/Chat/ChatTokenizedText.tsx +17 -10
  380. package/src/Chat/useChatComposerTokens.ts +1 -1
  381. package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
  382. package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
  383. package/src/CheckboxInput/CheckboxInput.tsx +8 -2
  384. package/src/ClickableCard/ClickableCard.tsx +3 -2
  385. package/src/CodeBlock/CodeBlock.doc.mjs +16 -4
  386. package/src/CodeBlock/CodeBlock.test.tsx +37 -0
  387. package/src/CodeBlock/CodeBlock.tsx +20 -4
  388. package/src/CodeBlock/highlightRanges.ts +1 -1
  389. package/src/CodeBlock/highlightStyles.ts +13 -13
  390. package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
  391. package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
  392. package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
  393. package/src/ContextMenu/ContextMenu.tsx +4 -3
  394. package/src/DateInput/DateInput.doc.mjs +16 -0
  395. package/src/DateInput/DateInput.tsx +55 -2
  396. package/src/DateInput/DateInputTouch.test.tsx +146 -32
  397. package/src/DateInput/NativeDateField.test.tsx +635 -0
  398. package/src/DateInput/NativeDateField.tsx +641 -0
  399. package/src/DateInput/TouchDateField.tsx +108 -24
  400. package/src/DateInput/index.ts +1 -0
  401. package/src/DateInput/nativeDateSegments.ts +127 -0
  402. package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
  403. package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
  404. package/src/DateTimeInput/DateTimeInput.tsx +556 -24
  405. package/src/DateTimeInput/index.ts +1 -0
  406. package/src/Dialog/Dialog.doc.mjs +8 -3
  407. package/src/Dialog/Dialog.test.tsx +429 -2
  408. package/src/Dialog/Dialog.tsx +133 -58
  409. package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
  410. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
  411. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
  412. package/src/Field/Field.doc.mjs +13 -2
  413. package/src/Field/FieldLabel.test.tsx +29 -0
  414. package/src/Field/FieldLabel.tsx +7 -0
  415. package/src/FileInput/FileInput.tsx +3 -2
  416. package/src/Heading/Heading.test.tsx +23 -1
  417. package/src/Heading/Heading.tsx +6 -2
  418. package/src/HoverCard/HoverCard.doc.mjs +13 -2
  419. package/src/HoverCard/HoverCard.test.tsx +154 -4
  420. package/src/HoverCard/HoverCard.tsx +143 -3
  421. package/src/HoverCard/useHoverCard.tsx +104 -33
  422. package/src/Indicator/CheckboxIndicator.tsx +14 -8
  423. package/src/Indicator/Indicator.doc.mjs +2 -0
  424. package/src/Item/Item.tsx +5 -4
  425. package/src/Kbd/Kbd.tsx +2 -19
  426. package/src/Layer/LayerDepthContext.tsx +62 -0
  427. package/src/Layer/index.ts +9 -0
  428. package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
  429. package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
  430. package/src/Layer/layerStack.ts +362 -0
  431. package/src/Layer/useLayer.test.tsx +62 -14
  432. package/src/Layer/useLayerDismissal.test.tsx +469 -0
  433. package/src/Layer/useLayerDismissal.ts +173 -0
  434. package/src/Layout/Layout.doc.mjs +2 -2
  435. package/src/Lightbox/Lightbox.doc.mjs +12 -0
  436. package/src/Lightbox/Lightbox.tsx +124 -102
  437. package/src/Link/Link.doc.mjs +39 -0
  438. package/src/Markdown/Markdown.doc.mjs +5 -0
  439. package/src/Markdown/Markdown.tsx +9 -4
  440. package/src/Markdown/incremental.test.ts +16 -2
  441. package/src/Markdown/index.ts +1 -0
  442. package/src/Markdown/parser.perf.test.ts +96 -1
  443. package/src/Markdown/parser.test.ts +178 -2
  444. package/src/Markdown/parser.ts +253 -32
  445. package/src/MobileNav/MobileNav.tsx +62 -36
  446. package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
  447. package/src/MultiSelector/MultiSelector.doc.mjs +49 -1
  448. package/src/MultiSelector/MultiSelector.test.tsx +277 -0
  449. package/src/MultiSelector/MultiSelector.tsx +142 -11
  450. package/src/MultiSelector/index.ts +1 -0
  451. package/src/NavIcon/NavIcon.doc.mjs +8 -2
  452. package/src/NavIcon/NavIcon.test.tsx +9 -0
  453. package/src/NavIcon/NavIcon.tsx +5 -1
  454. package/src/NavMenu/NavHeadingMenu.tsx +3 -2
  455. package/src/NumberInput/NumberInput.doc.mjs +31 -7
  456. package/src/NumberInput/NumberInput.test.tsx +436 -8
  457. package/src/NumberInput/NumberInput.tsx +62 -114
  458. package/src/NumberInput/numberInputCommit.test.ts +72 -0
  459. package/src/NumberInput/numberInputCommit.ts +103 -0
  460. package/src/NumberInput/numberParser.docblock.test.ts +234 -0
  461. package/src/NumberInput/numberParser.test.ts +222 -0
  462. package/src/NumberInput/numberParser.ts +403 -0
  463. package/src/Outline/Outline.tsx +3 -2
  464. package/src/OverflowList/OverflowList.tsx +3 -2
  465. package/src/Overlay/Overlay.tsx +3 -2
  466. package/src/Pagination/Pagination.test.tsx +3 -2
  467. package/src/Popover/usePopover.tsx +31 -28
  468. package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
  469. package/src/PowerSearch/PowerSearch.test.tsx +240 -1
  470. package/src/PowerSearch/PowerSearch.tsx +34 -5
  471. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +288 -0
  472. package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
  473. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +111 -1
  474. package/src/PowerSearch/PowerSearchValueEditor.tsx +124 -10
  475. package/src/PowerSearch/types.ts +2 -0
  476. package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
  477. package/src/PowerSearch/usePowerSearchSource.ts +13 -3
  478. package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
  479. package/src/ProgressBar/ProgressBar.test.tsx +24 -0
  480. package/src/ProgressBar/ProgressBar.tsx +28 -8
  481. package/src/Resizable/ResizeHandle.tsx +3 -2
  482. package/src/SegmentedControl/SegmentedControl.tsx +3 -2
  483. package/src/SelectableCard/SelectableCard.tsx +3 -2
  484. package/src/Selector/Selector.doc.mjs +26 -1
  485. package/src/Selector/Selector.test.tsx +311 -1
  486. package/src/Selector/Selector.tsx +139 -16
  487. package/src/SideNav/SideNav.doc.mjs +6 -6
  488. package/src/SideNav/SideNav.tsx +4 -2
  489. package/src/SideNav/SideNavHeading.tsx +12 -12
  490. package/src/SideNav/SideNavItem.tsx +4 -2
  491. package/src/Slider/Slider.test.tsx +106 -1
  492. package/src/Slider/Slider.tsx +55 -3
  493. package/src/Spinner/Spinner.test.tsx +147 -1
  494. package/src/Spinner/Spinner.tsx +120 -101
  495. package/src/StatusDot/StatusDot.doc.mjs +8 -2
  496. package/src/StatusDot/StatusDot.test.tsx +9 -0
  497. package/src/StatusDot/StatusDot.tsx +7 -1
  498. package/src/Stepper/Step.doc.mjs +98 -0
  499. package/src/Stepper/Step.tsx +1638 -0
  500. package/src/Stepper/StepStatus.ts +26 -0
  501. package/src/Stepper/Stepper.doc.mjs +370 -0
  502. package/src/Stepper/Stepper.test.tsx +1024 -0
  503. package/src/Stepper/Stepper.tsx +258 -0
  504. package/src/Stepper/StepperContext.ts +71 -0
  505. package/src/Stepper/index.ts +18 -0
  506. package/src/Stepper/stepper.stylex.ts +19 -0
  507. package/src/Switch/Switch.doc.mjs +2 -0
  508. package/src/Switch/Switch.test.tsx +10 -0
  509. package/src/Switch/Switch.tsx +6 -2
  510. package/src/TabList/Tab.doc.mjs +13 -1
  511. package/src/TabList/Tab.tsx +67 -7
  512. package/src/TabList/TabList.doc.mjs +22 -6
  513. package/src/TabList/TabList.test.tsx +559 -0
  514. package/src/TabList/TabList.tsx +490 -22
  515. package/src/TabList/TabListContext.ts +13 -2
  516. package/src/TabList/TabMenu.tsx +3 -2
  517. package/src/TabList/index.ts +6 -2
  518. package/src/Table/BaseTable.tsx +12 -4
  519. package/src/Table/Table.doc.mjs +9 -2
  520. package/src/Table/Table.test.tsx +132 -14
  521. package/src/Table/Table.tsx +3 -8
  522. package/src/Table/TableBody.doc.mjs +40 -0
  523. package/src/Table/TableFooter.doc.mjs +40 -0
  524. package/src/Table/TableHeader.doc.mjs +40 -0
  525. package/src/Table/TableRow.tsx +16 -5
  526. package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
  527. package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
  528. package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
  529. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
  530. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
  531. package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
  532. package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
  533. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
  534. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
  535. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
  536. package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
  537. package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
  538. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
  539. package/src/Table/types.ts +22 -4
  540. package/src/Table/useBaseTablePlugins.ts +5 -0
  541. package/src/Table/useTableGroupedRows.doc.mjs +5 -4
  542. package/src/Table/useTablePagination.doc.mjs +7 -0
  543. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  544. package/src/Table/useTableSelection.doc.mjs +31 -0
  545. package/src/Text/Text.test.tsx +23 -1
  546. package/src/Text/Text.tsx +6 -2
  547. package/src/TextArea/TextArea.doc.mjs +8 -2
  548. package/src/TextArea/TextArea.test.tsx +11 -0
  549. package/src/TextArea/TextArea.tsx +15 -8
  550. package/src/TextInput/TextInput.doc.mjs +10 -0
  551. package/src/TextInput/TextInput.tsx +3 -2
  552. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  553. package/src/TimeInput/TimeInput.tsx +2 -2
  554. package/src/Timestamp/Timestamp.test.tsx +18 -0
  555. package/src/Timestamp/Timestamp.tsx +4 -2
  556. package/src/Toast/Toast.doc.mjs +6 -0
  557. package/src/Toast/ToastViewport.tsx +17 -1
  558. package/src/Token/TokenLink.tsx +2 -2
  559. package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
  560. package/src/Tokenizer/Tokenizer.tsx +4 -0
  561. package/src/Toolbar/Toolbar.doc.mjs +5 -0
  562. package/src/Tooltip/Tooltip.doc.mjs +5 -0
  563. package/src/Tooltip/Tooltip.test.tsx +32 -0
  564. package/src/Tooltip/Tooltip.tsx +5 -0
  565. package/src/Tooltip/useTooltip.tsx +47 -24
  566. package/src/TopNav/TopNavHeading.tsx +5 -4
  567. package/src/TopNav/TopNavMegaMenu.tsx +3 -2
  568. package/src/TopNav/TopNavMenu.tsx +4 -3
  569. package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
  570. package/src/Typeahead/BaseTypeahead.tsx +85 -33
  571. package/src/Typeahead/Typeahead.doc.mjs +5 -0
  572. package/src/Typeahead/Typeahead.test.tsx +49 -0
  573. package/src/Typeahead/Typeahead.tsx +3 -2
  574. package/src/hooks/index.ts +2 -0
  575. package/src/hooks/useContainerReveal.doc.mjs +2 -2
  576. package/src/hooks/useFocusTrap.test.tsx +14 -0
  577. package/src/hooks/useFocusTrap.ts +62 -111
  578. package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
  579. package/src/hooks/useHotkeys.ts +3 -18
  580. package/src/hooks/useMergedRefs.doc.mjs +79 -0
  581. package/src/hooks/useMergedRefs.test.tsx +62 -0
  582. package/src/hooks/useMergedRefs.ts +36 -0
  583. package/src/index.ts +1 -0
  584. package/src/raw-import.d.ts +14 -0
  585. package/src/theme/MediaTheme.doc.mjs +5 -5
  586. package/src/theme/derivedVarRegistry.test.ts +19 -3
  587. package/src/theme/derivedVarRegistry.ts +23 -4
  588. package/src/theme/generateThemeRules.test.ts +37 -0
  589. package/src/theme/syntax/tokens.ts +5 -2
  590. package/src/utils/groupItems.ts +12 -6
  591. package/src/utils/index.ts +1 -1
  592. package/src/utils/isApplePlatform.test.ts +61 -0
  593. package/src/utils/isApplePlatform.ts +37 -0
  594. package/src/utils/sharedResizeObserver.ts +10 -2
  595. package/src/utils/timeParser.test.ts +6 -1
  596. package/src/utils/timeParser.ts +35 -13
  597. package/src/__tests__/inputWidthContract.test.tsx +0 -69
@@ -21,21 +21,75 @@ export const docs = {
21
21
  ],
22
22
  usage: {
23
23
  description:
24
- 'AlertDialog asks the user to confirm a destructive or irreversible action before it happens. Use it for things like deleting content, revoking access, or discarding unsaved changes.\n\nIt implements the WAI-ARIA APG [Alert Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): `role="alertdialog"`, a title linked by `aria-labelledby`, a consequence description linked by `aria-describedby`, focus moved into the dialog on open and returned to the trigger on close, and no dismissal by clicking outside. Escape cancels.\n\nFor cases where you want to show an alert without managing open state, use the `useImperativeAlertDialog` hook: call `alert.show(options)` and render `alert.element` in your tree.',
24
+ 'AlertDialog asks the user to confirm a destructive or irreversible action before it happens. Use it for things like deleting content, revoking access, or discarding unsaved changes.\n\nIt implements the WAI-ARIA APG [Alert Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): `role="alertdialog"`, a title linked by `aria-labelledby`, a consequence description linked by `aria-describedby`, focus moved into the dialog on open and returned to the trigger on close, and no dismissal by clicking outside. Escape cancels.\n\nAlertDialog passes its requested width through to Dialog, which clamps the surface to the container and dynamic viewport with token gutters. Generic Dialog footers should wrap, but Dialog does not own action semantics or order; consumer composition controls that. AlertDialog owns its confirmation semantics: above 640px, actions render horizontally and may move onto another row; at 640px and below, the destructive action appears above Cancel and both buttons fill the footer width. Button labels retain their standard single-line behavior. The breakpoint follows available width, not pointer or hover capability. The body scrolls when block space is constrained.\n\nFor cases where you want to show an alert without managing open state, use the `useImperativeAlertDialog` hook: call `alert.show(options)` and render `alert.element` in your tree.',
25
25
  bestPractices: [
26
- {guidance: true, description: 'Make the action button label specific: "Delete project" is better than "OK" or "Confirm".'},
27
- {guidance: true, description: 'Describe what will happen in the description so the user knows the consequences before confirming.'},
28
- {guidance: true, description: 'Keep the cancel button first: it takes initial focus, so the least destructive choice is the one already selected when the dialog opens.'},
29
- {guidance: false, description: 'Use AlertDialog for non-destructive actions; use a standard Dialog instead.'},
30
- {guidance: false, description: 'Rely on color alone to signal danger; the action label itself should say what will happen.'},
31
- {guidance: false, description: 'Close the dialog from onAction before the work finishes; hold it open with isActionLoading and call onOpenChange(false) when the action settles.'},
26
+ {
27
+ guidance: true,
28
+ description:
29
+ 'Make the action button label specific: "Delete project" is better than "OK" or "Confirm".',
30
+ },
31
+ {
32
+ guidance: true,
33
+ description:
34
+ 'Describe what will happen in the description so the user knows the consequences before confirming.',
35
+ },
36
+ {
37
+ guidance: true,
38
+ description:
39
+ 'Keep the cancel button as the least-destructive focus target. On narrow screens the destructive action is visually and structurally above Cancel, but Cancel still receives initial focus.',
40
+ },
41
+ {
42
+ guidance: true,
43
+ description:
44
+ 'Use concise, specific action labels. Above 640px, complete buttons may move onto another row; at 640px and below, the destructive action appears above Cancel and both buttons fill the footer width.',
45
+ },
46
+ {
47
+ guidance: false,
48
+ description:
49
+ 'Use AlertDialog for non-destructive actions; use a standard Dialog instead.',
50
+ },
51
+ {
52
+ guidance: false,
53
+ description:
54
+ 'Rely on color alone to signal danger; the action label itself should say what will happen.',
55
+ },
56
+ {
57
+ guidance: false,
58
+ description:
59
+ 'Close the dialog from onAction before the work finishes; hold it open with isActionLoading and call onOpenChange(false) when the action settles.',
60
+ },
32
61
  ],
33
62
  anatomy: [
34
- {name: 'Title', required: true, description: 'The question being asked. Renders as a level-2 heading and labels the dialog via aria-labelledby.'},
35
- {name: 'Description', required: true, description: 'What will happen if the user confirms. Linked to the dialog via aria-describedby.'},
36
- {name: 'Cancel button', required: true, description: 'Ghost button that dismisses without acting. Takes initial focus, and Escape does the same thing.'},
37
- {name: 'Action button', required: true, description: 'The confirming action. Destructive by default; shows a spinner while isActionLoading is set.'},
38
- {name: 'Backdrop', required: true, description: 'Overlay behind the dialog that blocks page interaction. Clicking it does not dismiss.'},
63
+ {
64
+ name: 'Title',
65
+ required: true,
66
+ description:
67
+ 'The question being asked. Renders as a level-2 heading and labels the dialog via aria-labelledby.',
68
+ },
69
+ {
70
+ name: 'Description',
71
+ required: true,
72
+ description:
73
+ 'What will happen if the user confirms. Linked to the dialog via aria-describedby.',
74
+ },
75
+ {
76
+ name: 'Cancel button',
77
+ required: true,
78
+ description:
79
+ 'Ghost button that dismisses without acting. Takes initial focus, and Escape does the same thing.',
80
+ },
81
+ {
82
+ name: 'Action button',
83
+ required: true,
84
+ description:
85
+ 'The confirming action. Destructive by default; shows a spinner while isActionLoading is set.',
86
+ },
87
+ {
88
+ name: 'Backdrop',
89
+ required: true,
90
+ description:
91
+ 'Overlay behind the dialog that blocks page interaction. Clicking it does not dismiss.',
92
+ },
39
93
  ],
40
94
  },
41
95
  // Intentionally a contained isInline preview, not playground.overlay: the
@@ -48,11 +102,13 @@ export const docs = {
48
102
  isInline: true,
49
103
  onOpenChange: undefined,
50
104
  title: 'Delete item?',
51
- description: 'This action cannot be undone. The item and all its data will be permanently removed.',
105
+ description:
106
+ 'This action cannot be undone. The item and all its data will be permanently removed.',
52
107
  actionLabel: 'Delete',
53
108
  },
54
109
  },
55
- description: 'A modal dialog that asks the user to confirm a destructive action.',
110
+ description:
111
+ 'A modal dialog that asks the user to confirm a destructive action.',
56
112
  props: [
57
113
  {
58
114
  name: 'isOpen',
@@ -111,38 +167,66 @@ export const docs = {
111
167
  name: 'width',
112
168
  type: 'number | string',
113
169
  default: '400',
114
- description: 'Dialog width.',
170
+ description:
171
+ 'Requested dialog width. Dialog preserves this preferred width and clamps it to the container and dynamic viewport with token gutters.',
115
172
  },
116
173
  {
117
174
  name: 'isInline',
118
175
  type: 'boolean',
119
176
  default: 'false',
120
- description: 'Renders alert dialog content inline without modal behavior. For documentation previews and showcases only. Not being a modal, the inline path renders role="group" instead of role="alertdialog".',
177
+ description:
178
+ 'Renders alert dialog content inline without modal behavior. For documentation previews and showcases only. Not being a modal, the inline path renders role="group" instead of role="alertdialog".',
121
179
  },
122
180
  ],
123
- components: [
124
- {name: 'useImperativeAlertDialog'},
125
- ],
181
+ components: [{name: 'useImperativeAlertDialog'}],
126
182
  theming: {
127
- targets: [
128
- {className: 'astryx-alert-dialog'},
129
- ],
183
+ targets: [{className: 'astryx-alert-dialog'}],
130
184
  },
131
185
  };
132
186
 
133
187
  /** @type {import('@astryxdesign/cli/authoring').ComponentTranslationDoc} */
134
188
  export const docsDense = {
135
- description: 'Confirms destructive/irreversible action before it happens (delete, revoke access, discard unsaved changes).',
189
+ description:
190
+ 'Confirms destructive/irreversible action before it happens (delete, revoke access, discard unsaved changes).',
136
191
  usage: {
137
192
  description:
138
- 'AlertDialog confirms destructive/irreversible action (delete, revoke access, discard changes). Implements WAI-ARIA APG Alert Dialog pattern (https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): role="alertdialog", aria-labelledby title, aria-describedby description, focus into dialog on open + back to trigger on close, no outside-click dismissal, Escape cancels. To show w/o managing open state, use useImperativeAlertDialog hook: call alert.show(options) + render alert.element in tree.',
193
+ 'AlertDialog confirms destructive/irreversible action (delete, revoke access, discard changes). Implements WAI-ARIA APG Alert Dialog pattern (https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): role="alertdialog", aria-labelledby title, aria-describedby description, focus into dialog on open + back to trigger on close, no outside-click dismissal, Escape cancels. Dialog preserves requested width + clamps it to container/dynamic viewport gutters. Generic Dialog footers wrap while consumers own action order. AlertDialog owns confirmation action layout: >640px horizontal buttons may move to another row; <=640px puts the destructive action above Cancel and makes both buttons full width regardless of pointer/hover capability. Button labels remain single-line. Body scrolls when height constrained. To show w/o managing open state, use useImperativeAlertDialog hook: call alert.show(options) + render alert.element in tree.',
139
194
  bestPractices: [
140
- {guidance: true, description: 'Make action button label specific: "Delete project" > "OK"/"Confirm".'},
141
- {guidance: true, description: 'Describe consequences in description so user knows outcome before confirming.'},
142
- {guidance: true, description: 'Keep cancel first: it takes initial focus, so least destructive choice is preselected.'},
143
- {guidance: false, description: 'Use AlertDialog for non-destructive actions; use standard Dialog instead.'},
144
- {guidance: false, description: 'Rely on color alone for danger; the action label should say what happens.'},
145
- {guidance: false, description: 'Close from onAction before work finishes; hold open w/ isActionLoading, call onOpenChange(false) when it settles.'},
195
+ {
196
+ guidance: true,
197
+ description:
198
+ 'Make action button label specific: "Delete project" > "OK"/"Confirm".',
199
+ },
200
+ {
201
+ guidance: true,
202
+ description:
203
+ 'Describe consequences in description so user knows outcome before confirming.',
204
+ },
205
+ {
206
+ guidance: true,
207
+ description:
208
+ 'Keep cancel as initial focus: least destructive choice is preselected even when narrow visual/DOM order places it after the destructive action.',
209
+ },
210
+ {
211
+ guidance: true,
212
+ description:
213
+ 'Use concise action labels; >640px complete buttons may move to another row, and <=640px puts the destructive action above Cancel with both buttons full width regardless of pointer type.',
214
+ },
215
+ {
216
+ guidance: false,
217
+ description:
218
+ 'Use AlertDialog for non-destructive actions; use standard Dialog instead.',
219
+ },
220
+ {
221
+ guidance: false,
222
+ description:
223
+ 'Rely on color alone for danger; the action label should say what happens.',
224
+ },
225
+ {
226
+ guidance: false,
227
+ description:
228
+ 'Close from onAction before work finishes; hold open w/ isActionLoading, call onOpenChange(false) when it settles.',
229
+ },
146
230
  ],
147
231
  },
148
232
  };
@@ -9,12 +9,65 @@
9
9
  * SYNC: When AlertDialog.tsx changes, update tests to match new behavior
10
10
  */
11
11
 
12
- import {describe, it, expect, vi, beforeEach} from 'vitest';
13
- import {render, screen, fireEvent, waitFor} from '@testing-library/react';
12
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
+ import {
14
+ render,
15
+ screen,
16
+ fireEvent,
17
+ waitFor,
18
+ within,
19
+ } from '@testing-library/react';
14
20
  import userEvent from '@testing-library/user-event';
15
21
  import {AlertDialog} from './AlertDialog';
16
22
  import {useImperativeAlertDialog} from './useImperativeAlertDialog';
17
23
 
24
+ function stubAlertDialogMedia({
25
+ smallScreen,
26
+ coarsePointer,
27
+ noHover,
28
+ reduceMotion = false,
29
+ }: {
30
+ smallScreen: boolean;
31
+ coarsePointer: boolean;
32
+ noHover: boolean;
33
+ reduceMotion?: boolean;
34
+ }): void {
35
+ vi.stubGlobal(
36
+ 'matchMedia',
37
+ vi.fn((query: string) => {
38
+ let matches = false;
39
+ if (query.includes('max-width: 640px')) {
40
+ matches = smallScreen;
41
+ } else if (query.includes('pointer: coarse')) {
42
+ matches = coarsePointer;
43
+ } else if (query.includes('pointer: fine')) {
44
+ matches = !coarsePointer;
45
+ } else if (query.includes('hover: none')) {
46
+ matches = noHover;
47
+ } else if (query.includes('hover: hover')) {
48
+ matches = !noHover;
49
+ } else if (query.includes('prefers-reduced-motion: reduce')) {
50
+ matches = reduceMotion;
51
+ } else if (query.includes('prefers-reduced-motion: no-preference')) {
52
+ matches = !reduceMotion;
53
+ } else if (query.includes('prefers-reduced-motion')) {
54
+ matches = reduceMotion;
55
+ }
56
+
57
+ return {
58
+ matches,
59
+ media: query,
60
+ onchange: null,
61
+ addEventListener: vi.fn(),
62
+ removeEventListener: vi.fn(),
63
+ addListener: vi.fn(),
64
+ removeListener: vi.fn(),
65
+ dispatchEvent: vi.fn(),
66
+ };
67
+ }),
68
+ );
69
+ }
70
+
18
71
  beforeEach(() => {
19
72
  HTMLDialogElement.prototype.showModal = vi.fn(function (
20
73
  this: HTMLDialogElement,
@@ -26,6 +79,10 @@ beforeEach(() => {
26
79
  });
27
80
  });
28
81
 
82
+ afterEach(() => {
83
+ vi.unstubAllGlobals();
84
+ });
85
+
29
86
  describe('AlertDialog', () => {
30
87
  const defaultProps = {
31
88
  isOpen: true,
@@ -109,6 +166,158 @@ describe('AlertDialog', () => {
109
166
  expect(screen.getByRole('alertdialog')).toBeInTheDocument();
110
167
  });
111
168
 
169
+ describe('responsive actions', () => {
170
+ const longCancelLabel = 'Keep this workspace and all of its dashboards';
171
+ const longActionLabel =
172
+ 'Permanently delete this workspace and all dashboards';
173
+
174
+ it('preserves the preferred width and horizontal order above the small breakpoint', () => {
175
+ stubAlertDialogMedia({
176
+ smallScreen: false,
177
+ coarsePointer: false,
178
+ noHover: false,
179
+ });
180
+ render(<AlertDialog {...defaultProps} />);
181
+
182
+ expect(window.matchMedia).toHaveBeenCalledWith('(max-width: 640px)');
183
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(pointer: coarse)');
184
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(hover: none)');
185
+ const dialog = screen.getByRole('alertdialog');
186
+ const buttons = within(dialog).getAllByRole('button');
187
+ const footerStack = buttons[0].parentElement!;
188
+ expect(dialog.getAttribute('style')).toContain('--x-width: 400px');
189
+ expect(dialog.getAttribute('style')).toContain(
190
+ '--x-maxWidth: min(100%, calc(100dvw - var(--spacing-4) - var(--spacing-4)))',
191
+ );
192
+ expect(buttons.map(button => button.textContent)).toEqual([
193
+ 'Cancel',
194
+ 'Delete',
195
+ ]);
196
+ expect(getComputedStyle(footerStack).flexWrap).toBe('wrap');
197
+ });
198
+
199
+ it('keeps long action buttons within the wide horizontal footer without changing Button sizing', () => {
200
+ stubAlertDialogMedia({
201
+ smallScreen: false,
202
+ coarsePointer: false,
203
+ noHover: false,
204
+ });
205
+ render(
206
+ <AlertDialog
207
+ {...defaultProps}
208
+ cancelLabel={longCancelLabel}
209
+ actionLabel={longActionLabel}
210
+ />,
211
+ );
212
+
213
+ const dialog = screen.getByRole('alertdialog');
214
+ const buttons = within(dialog).getAllByRole('button');
215
+ const footerStack = buttons[0].parentElement!;
216
+ expect(buttons.map(button => button.textContent)).toEqual([
217
+ longCancelLabel,
218
+ longActionLabel,
219
+ ]);
220
+ expect(getComputedStyle(footerStack).flexWrap).toBe('wrap');
221
+ for (const button of buttons) {
222
+ const computed = getComputedStyle(button);
223
+ expect(computed.whiteSpace).toBe('nowrap');
224
+ expect(computed.height).toBe('var(--size-element-md)');
225
+ expect(computed.maxWidth).toBe('100%');
226
+ }
227
+ });
228
+
229
+ it('stacks long destructive action labels above cancel on a narrow fine-pointer screen', () => {
230
+ stubAlertDialogMedia({
231
+ smallScreen: true,
232
+ coarsePointer: false,
233
+ noHover: false,
234
+ });
235
+ render(
236
+ <AlertDialog
237
+ {...defaultProps}
238
+ cancelLabel={longCancelLabel}
239
+ actionLabel={longActionLabel}
240
+ />,
241
+ );
242
+
243
+ expect(window.matchMedia).toHaveBeenCalledWith('(max-width: 640px)');
244
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(pointer: coarse)');
245
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(hover: none)');
246
+ const dialog = screen.getByRole('alertdialog');
247
+ const buttons = within(dialog).getAllByRole('button');
248
+ const footerStack = buttons[0].parentElement!;
249
+ expect(dialog.getAttribute('style')).toContain('--x-width: 400px');
250
+ expect(buttons.map(button => button.textContent)).toEqual([
251
+ longActionLabel,
252
+ longCancelLabel,
253
+ ]);
254
+ expect(getComputedStyle(footerStack).flexDirection).toBe('column');
255
+ for (const button of buttons) {
256
+ const computed = getComputedStyle(button);
257
+ expect(computed.whiteSpace).toBe('nowrap');
258
+ expect(computed.width).toBe('100%');
259
+ expect(computed.maxWidth).toBe('100%');
260
+ }
261
+ });
262
+
263
+ it('uses the same stacked layout on a mobile touch screen', () => {
264
+ stubAlertDialogMedia({
265
+ smallScreen: true,
266
+ coarsePointer: true,
267
+ noHover: true,
268
+ });
269
+ render(
270
+ <AlertDialog
271
+ {...defaultProps}
272
+ cancelLabel="Keep this workspace"
273
+ actionLabel="Permanently delete workspace"
274
+ />,
275
+ );
276
+
277
+ expect(window.matchMedia).toHaveBeenCalledWith('(max-width: 640px)');
278
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(pointer: coarse)');
279
+ expect(window.matchMedia).not.toHaveBeenCalledWith('(hover: none)');
280
+ const dialog = screen.getByRole('alertdialog');
281
+ const buttons = within(dialog).getAllByRole('button');
282
+ expect(dialog.getAttribute('style')).toContain('--x-width: 400px');
283
+ expect(buttons.map(button => button.textContent)).toEqual([
284
+ 'Permanently delete workspace',
285
+ 'Keep this workspace',
286
+ ]);
287
+ expect(getComputedStyle(buttons[0]).whiteSpace).toBe('nowrap');
288
+ expect(getComputedStyle(buttons[0]).width).toBe('100%');
289
+ expect(getComputedStyle(buttons[1]).whiteSpace).toBe('nowrap');
290
+ expect(getComputedStyle(buttons[1]).width).toBe('100%');
291
+ });
292
+
293
+ it('keeps narrow visual, DOM, and tab order aligned while autofocus stays on cancel', async () => {
294
+ const user = userEvent.setup();
295
+ stubAlertDialogMedia({
296
+ smallScreen: true,
297
+ coarsePointer: false,
298
+ noHover: false,
299
+ });
300
+ render(
301
+ <AlertDialog
302
+ {...defaultProps}
303
+ cancelLabel={longCancelLabel}
304
+ actionLabel={longActionLabel}
305
+ />,
306
+ );
307
+
308
+ const action = screen.getByRole('button', {name: longActionLabel});
309
+ const cancel = screen.getByRole('button', {name: longCancelLabel});
310
+ expect(
311
+ action.compareDocumentPosition(cancel) &
312
+ Node.DOCUMENT_POSITION_FOLLOWING,
313
+ ).toBeTruthy();
314
+ expect(cancel).toHaveAttribute('data-autofocus');
315
+ action.focus();
316
+ await user.tab();
317
+ expect(cancel).toHaveFocus();
318
+ });
319
+ });
320
+
112
321
  it('defaults cancel label to Cancel', () => {
113
322
  render(<AlertDialog {...defaultProps} />);
114
323
  expect(screen.getByText('Cancel')).toBeInTheDocument();
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file AlertDialog.tsx
7
- * @input Uses React, Dialog, Layout, Heading, Text, Button
7
+ * @input Uses React, StyleX, Dialog, Layout, Heading, Text, Button
8
8
  * @output Exports AlertDialog component, AlertDialogProps type
9
9
  * @position Core implementation; consumed by index.ts, tested by AlertDialog.test.tsx
10
10
  *
@@ -17,11 +17,12 @@
17
17
  */
18
18
 
19
19
  import React, {useId, useCallback} from 'react';
20
+ import * as stylex from '@stylexjs/stylex';
20
21
  import {Dialog} from '../Dialog';
21
22
  import {Layout} from '../Layout/Layout';
22
23
  import {LayoutContent} from '../Layout/LayoutContent';
23
24
  import {LayoutFooter} from '../Layout/LayoutFooter';
24
- import {HStack} from '../Stack';
25
+ import {Stack} from '../Stack';
25
26
  import {Heading} from '../Heading/Heading';
26
27
  import {Text} from '../Text/Text';
27
28
  import {Button, type ButtonVariant} from '../Button';
@@ -29,6 +30,19 @@ import type {BaseProps} from '../BaseProps';
29
30
  import {mergeProps} from '../utils';
30
31
  import {themeProps} from '../utils/themeProps';
31
32
  import {useTranslator} from '../i18n';
33
+ import {useMediaQuery} from '../hooks';
34
+
35
+ const SMALL_SCREEN_QUERY = '(max-width: 640px)';
36
+
37
+ const styles = stylex.create({
38
+ action: {
39
+ maxWidth: '100%',
40
+ minWidth: 0,
41
+ },
42
+ stackedAction: {
43
+ width: '100%',
44
+ },
45
+ });
32
46
 
33
47
  export interface AlertDialogProps extends BaseProps<HTMLDialogElement> {
34
48
  ref?: React.Ref<HTMLDialogElement>;
@@ -147,11 +161,44 @@ export function AlertDialog({
147
161
  const cancelLabel = cancelLabelFromProps ?? t('@astryx.alertDialog.cancel');
148
162
  const titleId = useId();
149
163
  const descriptionId = useId();
164
+ // Width stays delegated to Dialog: this query exists only so AlertDialog can
165
+ // keep narrow visual, DOM, and tab order aligned for its destructive/cancel
166
+ // semantics without coupling action order to pointer or hover capability.
167
+ const isSmallScreen = useMediaQuery(SMALL_SCREEN_QUERY);
150
168
 
151
169
  const handleCancel = useCallback(() => {
152
170
  onOpenChange(false);
153
171
  }, [onOpenChange]);
154
172
 
173
+ const buttonActionStyle = [
174
+ styles.action,
175
+ isSmallScreen && styles.stackedAction,
176
+ ];
177
+ const cancelButton = (
178
+ <Button
179
+ key="cancel"
180
+ variant="ghost"
181
+ label={cancelLabel}
182
+ onClick={handleCancel}
183
+ xstyle={buttonActionStyle}
184
+ // Dialog focuses [data-autofocus] itself after showModal(), because
185
+ // React's autoFocus runs during commit while the dialog is invisible.
186
+ // Cancel is least destructive, so it remains the autofocus target even
187
+ // when small-screen visual order places the destructive action above it.
188
+ data-autofocus
189
+ />
190
+ );
191
+ const actionButton = (
192
+ <Button
193
+ key="action"
194
+ variant={actionVariant}
195
+ label={actionLabel}
196
+ onClick={onAction}
197
+ isLoading={isActionLoading}
198
+ xstyle={buttonActionStyle}
199
+ />
200
+ );
201
+
155
202
  return (
156
203
  <Dialog
157
204
  {...rest}
@@ -185,24 +232,19 @@ export function AlertDialog({
185
232
  }
186
233
  footer={
187
234
  <LayoutFooter>
188
- <HStack gap={2} hAlign="end">
189
- <Button
190
- variant="ghost"
191
- label={cancelLabel}
192
- onClick={handleCancel}
193
- // Dialog focuses [data-autofocus] itself after showModal(),
194
- // because React's autoFocus runs during commit while the
195
- // dialog is still invisible. Cancel is the least destructive
196
- // choice, so it is the one that should be preselected.
197
- data-autofocus
198
- />
199
- <Button
200
- variant={actionVariant}
201
- label={actionLabel}
202
- onClick={onAction}
203
- isLoading={isActionLoading}
204
- />
205
- </HStack>
235
+ {/* Generic Dialog footers should wrap, but their consumers own
236
+ action semantics and order. AlertDialog keeps this
237
+ destructive-above-Cancel narrow order because confirmation
238
+ actions have component-specific meaning here. */}
239
+ <Stack
240
+ direction={isSmallScreen ? 'vertical' : 'horizontal'}
241
+ gap={2}
242
+ hAlign={isSmallScreen ? 'stretch' : 'end'}
243
+ wrap={isSmallScreen ? 'nowrap' : 'wrap'}>
244
+ {isSmallScreen
245
+ ? [actionButton, cancelButton]
246
+ : [cancelButton, actionButton]}
247
+ </Stack>
206
248
  </LayoutFooter>
207
249
  }
208
250
  />
@@ -50,7 +50,7 @@ import {AppShellMobileContext} from './AppShellMobileContext';
50
50
  import type {AppShellMobileContextValue} from './AppShellMobileContext';
51
51
  import type {SpacingStep} from '../utils/types';
52
52
  import type {BaseProps} from '../BaseProps';
53
- import {mergeProps, mergeRefs, isRenderable} from '../utils';
53
+ import {mergeProps, isRenderable} from '../utils';
54
54
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
55
55
  import {useMediaQuery} from '../hooks/useMediaQuery';
56
56
  import {observeResize, unobserveResize} from '../utils/sharedResizeObserver';
@@ -58,6 +58,7 @@ import {themeProps} from '../utils/themeProps';
58
58
  import {useTranslator} from '../i18n';
59
59
  import type {AppShellVariantMap} from './index';
60
60
 
61
+ import {useMergedRefs} from '../hooks/useMergedRefs';
61
62
  const HasActivity = typeof React.Activity !== 'undefined';
62
63
  const ActivityWrapper = HasActivity
63
64
  ? ({
@@ -792,7 +793,7 @@ export function AppShell({
792
793
  <AppShellMobileContext value={mobileContextValue}>
793
794
  <div
794
795
  {...rest}
795
- ref={mergeRefs(ref, shellRef)}
796
+ ref={useMergedRefs(ref, shellRef)}
796
797
  data-testid={dataTestId}
797
798
  {...mergeProps(
798
799
  themeProps('app-shell', {variant}),
@@ -16,6 +16,7 @@ export const docs = {
16
16
  {guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
17
17
  {guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
18
18
  {guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
19
+ {guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule; component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`); with only the conditional branch the ratio is unset outside the query and the box collapses.'},
19
20
  {guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
20
21
  {guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
21
22
  {guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
@@ -30,7 +31,7 @@ export const docs = {
30
31
  {
31
32
  name: 'ratio',
32
33
  type: 'number',
33
- description: 'Aspect ratio as width/height (e.g. 16/9, 1).',
34
+ description: 'Aspect ratio as width/height (e.g. 16/9, 1). Emitted as a class-level declaration (never inline), so `xstyle` rules or unlayered consumer CSS can override it responsively.',
34
35
  required: true,
35
36
  },
36
37
  {
@@ -83,6 +84,7 @@ export const docsZh = {
83
84
  {guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
84
85
  {guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
85
86
  {guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
87
+ {guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule; component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`); with only the conditional branch the ratio is unset outside the query and the box collapses.'},
86
88
  {guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
87
89
  {guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
88
90
  {guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
@@ -94,7 +96,7 @@ export const docsZh = {
94
96
  ],
95
97
  },
96
98
  props: [
97
- {name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1)。', required: true},
99
+ {name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1)。以类级声明输出(非内联样式),可通过 `xstyle` 规则或未分层的(unlayered)消费者 CSS 做响应式覆盖。', required: true},
98
100
  {
99
101
  name: 'shape',
100
102
  type: "'rectangle' | 'ellipse'",
@@ -133,6 +135,7 @@ export const docsDense = {
133
135
  {guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
134
136
  {guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
135
137
  {guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
138
+ {guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule; component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`); with only the conditional branch the ratio is unset outside the query and the box collapses.'},
136
139
  {guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
137
140
  {guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
138
141
  {guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
@@ -144,7 +147,7 @@ export const docsDense = {
144
147
  ],
145
148
  },
146
149
  propDescriptions: {
147
- ratio: 'width/height ratio (e.g. 16/9, 1)',
150
+ ratio: 'width/height ratio (e.g. 16/9, 1); class-level declaration (never inline) so xstyle/unlayered-CSS @container overrides win',
148
151
  shape: "container shape: 'rectangle' (default) | 'ellipse' (circle at ratio 1)",
149
152
  fit: "child layout: 'cover' fill+crop | 'contain' fill+letterbox | 'center' natural size; omitted = child styles itself",
150
153
  children: 'content positioned absolutely to fill container',