@astryxdesign/core 0.7.1 → 0.7.2-canary.020e1fe

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 (377) hide show
  1. package/dist/AppShell/AppShell.d.ts.map +1 -1
  2. package/dist/AppShell/AppShell.js +40 -1
  3. package/dist/AspectRatio/AspectRatio.d.ts +6 -8
  4. package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
  5. package/dist/AspectRatio/AspectRatio.js +44 -3
  6. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  7. package/dist/Breadcrumbs/BreadcrumbItem.js +5 -2
  8. package/dist/Button/Button.d.ts.map +1 -1
  9. package/dist/Button/Button.js +38 -14
  10. package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
  11. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  12. package/dist/CheckboxInput/CheckboxInput.js +3 -1
  13. package/dist/CheckboxList/CheckboxListItem.d.ts +9 -1
  14. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  15. package/dist/CheckboxList/CheckboxListItem.js +4 -2
  16. package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
  17. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  18. package/dist/CommandPalette/CommandPaletteInput.js +37 -5
  19. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  20. package/dist/ContextMenu/ContextMenu.js +5 -2
  21. package/dist/Dialog/Dialog.d.ts.map +1 -1
  22. package/dist/Dialog/Dialog.js +20 -8
  23. package/dist/Drawer/Drawer.d.ts +191 -0
  24. package/dist/Drawer/Drawer.d.ts.map +1 -0
  25. package/dist/Drawer/Drawer.js +382 -0
  26. package/dist/Drawer/DrawerHeader.d.ts +85 -0
  27. package/dist/Drawer/DrawerHeader.d.ts.map +1 -0
  28. package/dist/Drawer/DrawerHeader.js +134 -0
  29. package/dist/Drawer/index.d.ts +11 -0
  30. package/dist/Drawer/index.d.ts.map +1 -0
  31. package/dist/Drawer/index.js +11 -0
  32. package/dist/Drawer/useDrawerDialogPresence.d.ts +42 -0
  33. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -0
  34. package/dist/Drawer/useDrawerDialogPresence.js +236 -0
  35. package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
  36. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  37. package/dist/DropdownMenu/DropdownMenu.js +83 -11
  38. package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -0
  39. package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
  40. package/dist/DropdownMenu/DropdownMenuContext.js +21 -0
  41. package/dist/DropdownMenu/DropdownMenuDivider.d.ts +5 -3
  42. package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -1
  43. package/dist/DropdownMenu/DropdownMenuDivider.js +7 -3
  44. package/dist/DropdownMenu/DropdownMenuGroup.d.ts +6 -4
  45. package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
  46. package/dist/DropdownMenu/DropdownMenuGroup.js +4 -3
  47. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  48. package/dist/DropdownMenu/DropdownMenuSubMenu.js +19 -8
  49. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +24 -0
  50. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -0
  51. package/dist/DropdownMenu/lazyMenuBottomSheet.js +46 -0
  52. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  53. package/dist/EmptyState/EmptyState.js +4 -10
  54. package/dist/Field/Field.d.ts +1 -1
  55. package/dist/Field/Field.d.ts.map +1 -1
  56. package/dist/Field/Field.js +8 -4
  57. package/dist/Grid/GridSpan.d.ts.map +1 -1
  58. package/dist/Grid/GridSpan.js +1 -0
  59. package/dist/Heading/Heading.d.ts.map +1 -1
  60. package/dist/Heading/Heading.js +4 -2
  61. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  62. package/dist/HoverCard/useHoverCard.js +10 -2
  63. package/dist/Item/Item.d.ts +6 -2
  64. package/dist/Item/Item.d.ts.map +1 -1
  65. package/dist/Item/Item.js +19 -4
  66. package/dist/Layer/layerViewportInset.stylex.d.ts +6 -2
  67. package/dist/Layer/layerViewportInset.stylex.d.ts.map +1 -1
  68. package/dist/Layer/layerViewportInset.stylex.js +6 -2
  69. package/dist/Layer/useLayer.d.ts.map +1 -1
  70. package/dist/Layer/useLayer.js +13 -7
  71. package/dist/Layer/useLayerDismissal.d.ts +1 -1
  72. package/dist/Layer/useLayerDismissal.js +1 -1
  73. package/dist/Layout/container.stylex.d.ts +5 -5
  74. package/dist/Layout/container.stylex.js +4 -4
  75. package/dist/List/List.d.ts +46 -19
  76. package/dist/List/List.d.ts.map +1 -1
  77. package/dist/List/List.js +28 -10
  78. package/dist/List/ListContext.d.ts +8 -3
  79. package/dist/List/ListContext.d.ts.map +1 -1
  80. package/dist/List/ListContext.js +7 -2
  81. package/dist/List/ListItem.d.ts +13 -5
  82. package/dist/List/ListItem.d.ts.map +1 -1
  83. package/dist/List/ListItem.js +21 -8
  84. package/dist/List/index.d.ts +1 -1
  85. package/dist/List/index.d.ts.map +1 -1
  86. package/dist/Markdown/Markdown.d.ts.map +1 -1
  87. package/dist/Markdown/Markdown.js +8 -1
  88. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -1
  89. package/dist/Markdown/plugins/frontmatter.js +7 -3
  90. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  91. package/dist/MetadataList/MetadataList.js +5 -1
  92. package/dist/MetadataList/MetadataListContext.d.ts +1 -1
  93. package/dist/MetadataList/MetadataListContext.d.ts.map +1 -1
  94. package/dist/MobileNav/MobileNav.d.ts +9 -0
  95. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  96. package/dist/MobileNav/MobileNav.js +30 -3
  97. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  98. package/dist/MultiSelector/MultiSelector.js +22 -8
  99. package/dist/MultiSelector/OptionActions.a11y.chromium.spec.js +100 -2
  100. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  101. package/dist/MultiSelector/hooks.js +3 -1
  102. package/dist/Pagination/Pagination.d.ts +8 -5
  103. package/dist/Pagination/Pagination.d.ts.map +1 -1
  104. package/dist/Pagination/Pagination.js +21 -8
  105. package/dist/Popover/Popover.js +2 -2
  106. package/dist/PowerSearch/PowerSearch.js +1 -1
  107. package/dist/RadioList/RadioList.d.ts +1 -1
  108. package/dist/RadioList/RadioList.d.ts.map +1 -1
  109. package/dist/RadioList/RadioList.js +6 -2
  110. package/dist/RadioList/RadioListItem.d.ts +9 -1
  111. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  112. package/dist/RadioList/RadioListItem.js +2 -0
  113. package/dist/Selector/hooks.d.ts.map +1 -1
  114. package/dist/Selector/hooks.js +6 -2
  115. package/dist/SideNav/SideNavItem.d.ts +8 -1
  116. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  117. package/dist/SideNav/SideNavItem.js +71 -9
  118. package/dist/Switch/Switch.d.ts +1 -1
  119. package/dist/Switch/Switch.d.ts.map +1 -1
  120. package/dist/Switch/Switch.js +13 -1
  121. package/dist/TabList/TabMenu.d.ts +2 -2
  122. package/dist/TabList/TabMenu.d.ts.map +1 -1
  123. package/dist/TabList/TabMenu.js +6 -3
  124. package/dist/Text/Text.d.ts.map +1 -1
  125. package/dist/Text/Text.js +4 -2
  126. package/dist/Text/useTruncation.d.ts +7 -5
  127. package/dist/Text/useTruncation.d.ts.map +1 -1
  128. package/dist/Text/useTruncation.js +16 -5
  129. package/dist/ToggleButton/ToggleButton.d.ts +3 -2
  130. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  131. package/dist/ToggleButton/ToggleButton.js +12 -1
  132. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  133. package/dist/Tooltip/useTooltip.js +11 -0
  134. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  135. package/dist/TopNav/TopNavMegaMenu.js +3 -3
  136. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  137. package/dist/TopNav/TopNavMenu.js +3 -3
  138. package/dist/TreeList/TreeList.d.ts.map +1 -1
  139. package/dist/TreeList/TreeList.js +1 -0
  140. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  141. package/dist/TreeList/TreeListBranches.js +2 -2
  142. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  143. package/dist/TreeList/TreeListItem.js +57 -9
  144. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  145. package/dist/Typeahead/BaseTypeahead.js +26 -0
  146. package/dist/astryx.css +47 -13
  147. package/dist/hooks/useEntryAnimation.d.ts +2 -1
  148. package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
  149. package/dist/hooks/useEntryAnimation.js +14 -12
  150. package/dist/hooks/useIsHydrating.d.ts +6 -0
  151. package/dist/hooks/useIsHydrating.d.ts.map +1 -0
  152. package/dist/hooks/useIsHydrating.js +30 -0
  153. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  154. package/dist/hooks/useMenuHover.js +18 -13
  155. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  156. package/dist/i18n/generated-locales/en.generated.js +112 -1
  157. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  158. package/dist/i18n/generated-locales/pseudo.generated.js +112 -1
  159. package/dist/index.d.ts +1 -0
  160. package/dist/index.d.ts.map +1 -1
  161. package/dist/index.js +1 -0
  162. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  163. package/dist/theme/derivedVarRegistry.js +0 -3
  164. package/dist/utils/focusOutline.stylex.d.ts +4 -0
  165. package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
  166. package/dist/utils/focusOutline.stylex.js +4 -0
  167. package/dist/utils/plainDate.d.ts.map +1 -1
  168. package/dist/utils/plainDate.js +15 -9
  169. package/dist/utils/sharedMutationObserver.d.ts +21 -0
  170. package/dist/utils/sharedMutationObserver.d.ts.map +1 -0
  171. package/dist/utils/sharedMutationObserver.js +69 -0
  172. package/locales/en.json +444 -0
  173. package/locales/pseudo.json +333 -0
  174. package/package.json +9 -4
  175. package/scripts/agent-doc-state.mjs +38 -0
  176. package/scripts/postinstall.mjs +1 -1
  177. package/src/AppShell/AppShell.tsx +45 -1
  178. package/src/AspectRatio/AspectRatio.test.tsx +44 -43
  179. package/src/AspectRatio/AspectRatio.tsx +38 -18
  180. package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +157 -0
  181. package/src/Avatar/Avatar.doc.mjs +5 -3
  182. package/src/AvatarGroup/AvatarGroup.doc.mjs +3 -2
  183. package/src/Breadcrumbs/BreadcrumbItem.tsx +4 -1
  184. package/src/Breadcrumbs/Breadcrumbs.test.tsx +30 -1
  185. package/src/Button/Button.doc.mjs +2 -2
  186. package/src/Button/Button.test.tsx +155 -9
  187. package/src/Button/Button.tsx +39 -16
  188. package/src/Button/__tests__/Button.a11y.known-failures.ts +1 -62
  189. package/src/Button/__tests__/Button.a11y.states.ts +0 -10
  190. package/src/Card/Card.doc.mjs +1 -1
  191. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +3 -1
  192. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  193. package/src/CheckboxInput/CheckboxInput.tsx +3 -1
  194. package/src/CheckboxList/CheckboxList.test.tsx +22 -0
  195. package/src/CheckboxList/CheckboxListItem.doc.mjs +16 -0
  196. package/src/CheckboxList/CheckboxListItem.tsx +10 -0
  197. package/src/Code/Code.doc.mjs +1 -0
  198. package/src/CommandPalette/CommandPalette.doc.mjs +2 -0
  199. package/src/CommandPalette/CommandPaletteInput.test.tsx +53 -4
  200. package/src/CommandPalette/CommandPaletteInput.tsx +33 -3
  201. package/src/CommandPalette/__tests__/CommandPaletteInputAudit.a11y.chromium.spec.ts +335 -0
  202. package/src/CommandPalette/__tests__/CommandPaletteItemAudit.a11y.chromium.spec.ts +292 -0
  203. package/src/ContextMenu/ContextMenu.doc.mjs +2 -3
  204. package/src/ContextMenu/ContextMenu.tsx +4 -1
  205. package/src/ContextMenu/__tests__/ContextMenuAudit.a11y.chromium.spec.ts +438 -0
  206. package/src/Dialog/Dialog.test.tsx +46 -0
  207. package/src/Dialog/Dialog.tsx +20 -7
  208. package/src/Dialog/__tests__/Dialog.a11y.known-failures.ts +0 -14
  209. package/src/Drawer/Drawer.doc.mjs +473 -0
  210. package/src/Drawer/Drawer.spec.md +357 -0
  211. package/src/Drawer/Drawer.test.tsx +1300 -0
  212. package/src/Drawer/Drawer.tsx +613 -0
  213. package/src/Drawer/DrawerDirection.test.tsx +127 -0
  214. package/src/Drawer/DrawerHeader.doc.mjs +293 -0
  215. package/src/Drawer/DrawerHeader.test.tsx +102 -0
  216. package/src/Drawer/DrawerHeader.tsx +235 -0
  217. package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +401 -0
  218. package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +297 -0
  219. package/src/Drawer/index.ts +13 -0
  220. package/src/Drawer/useDrawerDialogPresence.ts +284 -0
  221. package/src/DropdownMenu/DropdownMenu.ssr.test.tsx +57 -0
  222. package/src/DropdownMenu/DropdownMenu.test.tsx +79 -18
  223. package/src/DropdownMenu/DropdownMenu.tsx +83 -12
  224. package/src/DropdownMenu/DropdownMenuContext.tsx +24 -0
  225. package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +2 -2
  226. package/src/DropdownMenu/DropdownMenuDivider.spec.md +192 -0
  227. package/src/DropdownMenu/DropdownMenuDivider.tsx +9 -5
  228. package/src/DropdownMenu/DropdownMenuGroup.doc.mjs +169 -10
  229. package/src/DropdownMenu/DropdownMenuGroup.tsx +6 -4
  230. package/src/DropdownMenu/DropdownMenuLazySheet.test.tsx +126 -0
  231. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +185 -0
  232. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +19 -5
  233. package/src/DropdownMenu/__tests__/DropdownMenuDividerAudit.a11y.chromium.spec.ts +280 -0
  234. package/src/DropdownMenu/__tests__/DropdownMenuGroupAudit.a11y.chromium.spec.ts +334 -0
  235. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +145 -0
  236. package/src/DropdownMenu/__tests__/Menu.a11y.known-failures.ts +26 -0
  237. package/src/DropdownMenu/__tests__/Menu.a11y.renders.tsx +65 -0
  238. package/src/DropdownMenu/__tests__/Menu.a11y.states.ts +138 -0
  239. package/src/DropdownMenu/__tests__/Menu.a11y.test.tsx +136 -0
  240. package/src/DropdownMenu/__tests__/warmMenuBottomSheet.tsx +43 -0
  241. package/src/DropdownMenu/lazyMenuBottomSheet.ts +71 -0
  242. package/src/EmptyState/EmptyState.doc.mjs +3 -2
  243. package/src/EmptyState/EmptyState.spec.md +189 -0
  244. package/src/EmptyState/EmptyState.test.tsx +74 -3
  245. package/src/EmptyState/EmptyState.tsx +4 -8
  246. package/src/Field/Field.doc.mjs +14 -8
  247. package/src/Field/Field.spec.md +217 -0
  248. package/src/Field/Field.test.tsx +60 -2
  249. package/src/Field/Field.tsx +17 -8
  250. package/src/Field/FieldLabel.doc.mjs +133 -26
  251. package/src/Field/FieldLabel.spec.md +172 -0
  252. package/src/Field/__tests__/FieldLabelAudit.a11y.chromium.spec.ts +296 -0
  253. package/src/Grid/GridSpan.tsx +3 -0
  254. package/src/Heading/Heading.test.tsx +57 -0
  255. package/src/Heading/Heading.tsx +6 -2
  256. package/src/HoverCard/HoverCard.test.tsx +58 -0
  257. package/src/HoverCard/useHoverCard.tsx +10 -2
  258. package/src/Icon/Icon.doc.mjs +36 -0
  259. package/src/IconButton/IconButton.doc.mjs +2 -2
  260. package/src/IconButton/IconButton.test.tsx +3 -1
  261. package/src/Item/Item.doc.mjs +12 -8
  262. package/src/Item/Item.spec.md +226 -0
  263. package/src/Item/Item.test.tsx +61 -0
  264. package/src/Item/Item.tsx +40 -4
  265. package/src/Layer/layerViewportInset.source-build.test.mjs +90 -0
  266. package/src/Layer/layerViewportInset.stylex.ts +6 -2
  267. package/src/Layer/layerViewportInset.test.ts +1 -0
  268. package/src/Layer/useLayer.tsx +24 -13
  269. package/src/Layer/useLayerDismissal.ts +1 -1
  270. package/src/Layout/LayoutHeader.doc.mjs +5 -0
  271. package/src/Layout/container.stylex.ts +6 -6
  272. package/src/List/List.doc.mjs +14 -1
  273. package/src/List/List.spec.md +129 -77
  274. package/src/List/List.test.tsx +163 -94
  275. package/src/List/List.tsx +74 -18
  276. package/src/List/ListContext.tsx +9 -3
  277. package/src/List/ListItem.doc.mjs +24 -5
  278. package/src/List/ListItem.tsx +56 -27
  279. package/src/List/index.ts +1 -1
  280. package/src/Markdown/Markdown.tsx +14 -1
  281. package/src/Markdown/plugins/frontmatter.test.tsx +25 -0
  282. package/src/Markdown/plugins/frontmatter.ts +7 -3
  283. package/src/MetadataList/MetadataList.doc.mjs +3 -3
  284. package/src/MetadataList/MetadataList.test.tsx +38 -0
  285. package/src/MetadataList/MetadataList.tsx +8 -1
  286. package/src/MetadataList/MetadataListContext.tsx +1 -1
  287. package/src/MobileNav/MobileNav.tsx +30 -3
  288. package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +173 -15
  289. package/src/MoreMenu/MoreMenu.test.tsx +5 -1
  290. package/src/MultiSelector/MultiSelector.test.tsx +159 -0
  291. package/src/MultiSelector/MultiSelector.tsx +40 -7
  292. package/src/MultiSelector/OptionActions.a11y.chromium.spec.ts +112 -2
  293. package/src/MultiSelector/hooks.ts +3 -1
  294. package/src/MultiSelector/useMultiCombobox.doc.mjs +267 -0
  295. package/src/Pagination/Pagination.doc.mjs +7 -7
  296. package/src/Pagination/Pagination.spec.md +9 -9
  297. package/src/Pagination/Pagination.test.tsx +242 -0
  298. package/src/Pagination/Pagination.tsx +27 -11
  299. package/src/Popover/Popover.test.tsx +2 -2
  300. package/src/Popover/Popover.tsx +4 -4
  301. package/src/PowerSearch/PowerSearch.test.tsx +85 -0
  302. package/src/PowerSearch/PowerSearch.tsx +2 -2
  303. package/src/ProgressBar/ProgressBar.doc.mjs +1 -0
  304. package/src/RadioList/RadioList.fr10.test.tsx +45 -2
  305. package/src/RadioList/RadioList.test.tsx +22 -0
  306. package/src/RadioList/RadioList.tsx +4 -1
  307. package/src/RadioList/RadioListItem.doc.mjs +16 -0
  308. package/src/RadioList/RadioListItem.tsx +10 -1
  309. package/src/Resizable/useResizable.doc.mjs +2 -0
  310. package/src/ScrollableArea/ScrollableArea.doc.mjs +1 -1
  311. package/src/Selector/hooks.ts +6 -2
  312. package/src/Selector/useCombobox.doc.mjs +237 -0
  313. package/src/SideNav/SideNav.spec.md +227 -0
  314. package/src/SideNav/SideNav.test.tsx +179 -0
  315. package/src/SideNav/SideNavItem.doc.mjs +2 -2
  316. package/src/SideNav/SideNavItem.tsx +96 -17
  317. package/src/Slider/Slider.spec.md +39 -18
  318. package/src/Spinner/Spinner.doc.mjs +1 -1
  319. package/src/Switch/Switch.test.tsx +49 -0
  320. package/src/Switch/Switch.tsx +11 -0
  321. package/src/TabList/TabList.spec.md +57 -44
  322. package/src/TabList/TabList.test.tsx +67 -0
  323. package/src/TabList/TabMenu.doc.mjs +4 -3
  324. package/src/TabList/TabMenu.tsx +7 -4
  325. package/src/Text/Text.test.tsx +57 -0
  326. package/src/Text/Text.tsx +6 -2
  327. package/src/Text/useTruncation.test.tsx +69 -0
  328. package/src/Text/useTruncation.ts +16 -5
  329. package/src/TimeInput/TimeInput.fr10.test.tsx +15 -0
  330. package/src/Timestamp/Timestamp.doc.mjs +1 -1
  331. package/src/ToggleButton/ToggleButton.test.tsx +95 -0
  332. package/src/ToggleButton/ToggleButton.tsx +12 -1
  333. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +4 -0
  334. package/src/Tokenizer/Tokenizer.test.tsx +54 -1
  335. package/src/Toolbar/Toolbar.test.tsx +0 -8
  336. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +163 -0
  337. package/src/Toolbar/__tests__/Toolbar.a11y.renders.tsx +63 -0
  338. package/src/Toolbar/__tests__/Toolbar.a11y.states.ts +142 -0
  339. package/src/Toolbar/__tests__/Toolbar.a11y.test.tsx +126 -0
  340. package/src/Tooltip/Tooltip.test.tsx +31 -0
  341. package/src/Tooltip/useTooltip.test.tsx +13 -0
  342. package/src/Tooltip/useTooltip.tsx +11 -0
  343. package/src/TopNav/TopNavMegaMenu.test.tsx +22 -0
  344. package/src/TopNav/TopNavMegaMenu.tsx +7 -3
  345. package/src/TopNav/TopNavMenu.test.tsx +19 -0
  346. package/src/TopNav/TopNavMenu.tsx +11 -3
  347. package/src/TreeList/TreeList.doc.mjs +1 -0
  348. package/src/TreeList/TreeList.spec.md +29 -17
  349. package/src/TreeList/TreeList.test.tsx +327 -6
  350. package/src/TreeList/TreeList.tsx +5 -1
  351. package/src/TreeList/TreeListBranches.tsx +6 -0
  352. package/src/TreeList/TreeListItem.tsx +88 -13
  353. package/src/Typeahead/BaseTypeahead.tsx +26 -0
  354. package/src/Typeahead/Typeahead.test.tsx +260 -2
  355. package/src/docPropLiterals.test.ts +36 -10
  356. package/src/hooks/useEntryAnimation.doc.mjs +4 -4
  357. package/src/hooks/useEntryAnimation.ssr.test.tsx +143 -0
  358. package/src/hooks/useEntryAnimation.ts +15 -16
  359. package/src/hooks/useIsHydrating.test.tsx +70 -0
  360. package/src/hooks/useIsHydrating.ts +31 -0
  361. package/src/hooks/useMenuHover.ts +18 -13
  362. package/src/i18n/InternationalizationProvider.doc.mjs +8 -0
  363. package/src/i18n/InternationalizationProvider.spec.md +252 -0
  364. package/src/i18n/__tests__/InternationalizationProvider.test.tsx +128 -0
  365. package/src/i18n/generated-locales/en.generated.ts +121 -0
  366. package/src/i18n/generated-locales/pseudo.generated.ts +121 -0
  367. package/src/i18n/useTranslator.test.tsx +37 -0
  368. package/src/index.ts +1 -0
  369. package/src/postinstall.test.mjs +46 -0
  370. package/src/reset.css +0 -29
  371. package/src/theme/derivedVarRegistry.test.ts +7 -3
  372. package/src/theme/derivedVarRegistry.ts +0 -3
  373. package/src/utils/focusOutline.stylex.ts +4 -0
  374. package/src/utils/plainDate.test.ts +37 -1
  375. package/src/utils/plainDate.ts +15 -5
  376. package/src/utils/sharedMutationObserver.test.ts +53 -0
  377. package/src/utils/sharedMutationObserver.ts +78 -0
@@ -0,0 +1,438 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file ContextMenuAudit.a11y.chromium.spec.ts
5
+ * @input Exact-head ContextMenu stories across pointer/touch presentation, state, theme, direction, and viewport
6
+ * @output Screenshots and fail-closed sensor receipts for the ContextMenu whole-component audit
7
+ * @position Component-owned Night Watch browser evidence; CI runs it only for a ContextMenu audit pull request
8
+ */
9
+
10
+ import {createHash} from 'node:crypto';
11
+ import {execFileSync} from 'node:child_process';
12
+ import * as fs from 'node:fs';
13
+ import * as path from 'node:path';
14
+ import {expect, test, type Locator, type Page} from '@playwright/test';
15
+ import {holdMotionStill} from '@astryxdesign/a11y-spec/chromium';
16
+ import {
17
+ DEFAULT_STORYBOOK_DIR,
18
+ serveStorybook,
19
+ type StaticServer,
20
+ } from '@astryxdesign/a11y-spec/storybook';
21
+
22
+ const OUTPUT = path.resolve('context-menu-audit-evidence');
23
+ const WIDE = {width: 1024, height: 768};
24
+ const NARROW = {width: 320, height: 720};
25
+
26
+ type Mode = 'light' | 'dark';
27
+ type Direction = 'ltr' | 'rtl';
28
+ type Theme = 'neutral' | 'butter';
29
+ type Surface = 'menu' | 'dialog';
30
+ type AuditCase = {
31
+ key: string;
32
+ storyId: string;
33
+ mode: Mode;
34
+ direction: Direction;
35
+ theme: Theme;
36
+ viewport: {width: number; height: number};
37
+ surface: Surface;
38
+ triggerText?: string;
39
+ menuName?: string;
40
+ expectedState?: 'default' | 'disabled' | 'sections' | 'selectable';
41
+ };
42
+
43
+ const cases: AuditCase[] = [
44
+ {
45
+ key: 'pointer-neutral-light',
46
+ storyId: 'core-contextmenu--pointer-presentation',
47
+ mode: 'light',
48
+ direction: 'ltr',
49
+ theme: 'neutral',
50
+ viewport: WIDE,
51
+ surface: 'menu',
52
+ menuName: 'Document actions',
53
+ },
54
+ {
55
+ key: 'pointer-neutral-dark',
56
+ storyId: 'core-contextmenu--pointer-presentation',
57
+ mode: 'dark',
58
+ direction: 'ltr',
59
+ theme: 'neutral',
60
+ viewport: WIDE,
61
+ surface: 'menu',
62
+ menuName: 'Document actions',
63
+ },
64
+ {
65
+ key: 'pointer-butter-light',
66
+ storyId: 'core-contextmenu--pointer-presentation',
67
+ mode: 'light',
68
+ direction: 'ltr',
69
+ theme: 'butter',
70
+ viewport: WIDE,
71
+ surface: 'menu',
72
+ menuName: 'Document actions',
73
+ },
74
+ {
75
+ key: 'pointer-butter-dark',
76
+ storyId: 'core-contextmenu--pointer-presentation',
77
+ mode: 'dark',
78
+ direction: 'ltr',
79
+ theme: 'butter',
80
+ viewport: WIDE,
81
+ surface: 'menu',
82
+ menuName: 'Document actions',
83
+ },
84
+ {
85
+ key: 'pointer-rtl-light',
86
+ storyId: 'core-contextmenu--pointer-presentation',
87
+ mode: 'light',
88
+ direction: 'rtl',
89
+ theme: 'neutral',
90
+ viewport: WIDE,
91
+ surface: 'menu',
92
+ menuName: 'Document actions',
93
+ },
94
+ {
95
+ key: 'pointer-rtl-dark',
96
+ storyId: 'core-contextmenu--pointer-presentation',
97
+ mode: 'dark',
98
+ direction: 'rtl',
99
+ theme: 'neutral',
100
+ viewport: WIDE,
101
+ surface: 'menu',
102
+ menuName: 'Document actions',
103
+ },
104
+ {
105
+ key: 'pointer-narrow-light',
106
+ storyId: 'core-contextmenu--pointer-presentation',
107
+ mode: 'light',
108
+ direction: 'ltr',
109
+ theme: 'neutral',
110
+ viewport: NARROW,
111
+ surface: 'menu',
112
+ menuName: 'Document actions',
113
+ },
114
+ {
115
+ key: 'pointer-narrow-dark',
116
+ storyId: 'core-contextmenu--pointer-presentation',
117
+ mode: 'dark',
118
+ direction: 'ltr',
119
+ theme: 'neutral',
120
+ viewport: NARROW,
121
+ surface: 'menu',
122
+ menuName: 'Document actions',
123
+ },
124
+ {
125
+ key: 'disabled-item-light',
126
+ storyId: 'core-contextmenu--with-disabled-items',
127
+ mode: 'light',
128
+ direction: 'ltr',
129
+ theme: 'neutral',
130
+ viewport: WIDE,
131
+ surface: 'menu',
132
+ triggerText: 'Right-click this area',
133
+ expectedState: 'disabled',
134
+ },
135
+ {
136
+ key: 'sections-dark',
137
+ storyId: 'core-contextmenu--with-sections',
138
+ mode: 'dark',
139
+ direction: 'ltr',
140
+ theme: 'neutral',
141
+ viewport: WIDE,
142
+ surface: 'menu',
143
+ triggerText: 'Right-click for grouped actions',
144
+ expectedState: 'sections',
145
+ },
146
+ {
147
+ key: 'selectable-light',
148
+ storyId: 'core-contextmenu--with-selectable-items',
149
+ mode: 'light',
150
+ direction: 'ltr',
151
+ theme: 'neutral',
152
+ viewport: WIDE,
153
+ surface: 'menu',
154
+ triggerText: 'Right-click for selectable items',
155
+ expectedState: 'selectable',
156
+ },
157
+ {
158
+ key: 'selectable-dark',
159
+ storyId: 'core-contextmenu--with-selectable-items',
160
+ mode: 'dark',
161
+ direction: 'ltr',
162
+ theme: 'neutral',
163
+ viewport: WIDE,
164
+ surface: 'menu',
165
+ triggerText: 'Right-click for selectable items',
166
+ expectedState: 'selectable',
167
+ },
168
+ {
169
+ key: 'sheet-light',
170
+ storyId: 'core-contextmenu--bottom-sheet-presentation',
171
+ mode: 'light',
172
+ direction: 'ltr',
173
+ theme: 'neutral',
174
+ viewport: NARROW,
175
+ surface: 'dialog',
176
+ },
177
+ {
178
+ key: 'sheet-dark',
179
+ storyId: 'core-contextmenu--bottom-sheet-presentation',
180
+ mode: 'dark',
181
+ direction: 'ltr',
182
+ theme: 'neutral',
183
+ viewport: NARROW,
184
+ surface: 'dialog',
185
+ },
186
+ {
187
+ key: 'sheet-rtl',
188
+ storyId: 'core-contextmenu--bottom-sheet-presentation',
189
+ mode: 'light',
190
+ direction: 'rtl',
191
+ theme: 'neutral',
192
+ viewport: NARROW,
193
+ surface: 'dialog',
194
+ },
195
+ {
196
+ key: 'inline-light',
197
+ storyId: 'core-contextmenu--inline-trigger',
198
+ mode: 'light',
199
+ direction: 'ltr',
200
+ theme: 'neutral',
201
+ viewport: WIDE,
202
+ surface: 'menu',
203
+ triggerText: 'T123',
204
+ menuName: 'Task actions',
205
+ },
206
+ {
207
+ key: 'inline-dark',
208
+ storyId: 'core-contextmenu--inline-trigger',
209
+ mode: 'dark',
210
+ direction: 'ltr',
211
+ theme: 'neutral',
212
+ viewport: WIDE,
213
+ surface: 'menu',
214
+ triggerText: 'T123',
215
+ menuName: 'Task actions',
216
+ },
217
+ {
218
+ key: 'scroll-container-light',
219
+ storyId: 'core-contextmenu--in-scroll-container',
220
+ mode: 'light',
221
+ direction: 'ltr',
222
+ theme: 'neutral',
223
+ viewport: WIDE,
224
+ surface: 'menu',
225
+ triggerText: 'Right-click this area',
226
+ },
227
+ ];
228
+
229
+ test.describe.configure({mode: 'serial', retries: 0});
230
+ let server: StaticServer;
231
+ let checkoutSha: string;
232
+ let storybookSha: string;
233
+
234
+ function storyUrl(item: AuditCase) {
235
+ return `${server.origin}/iframe.html?id=${item.storyId}&viewMode=story&globals=colorMode:${item.mode};astryxTheme:${item.theme};direction:${item.direction}`;
236
+ }
237
+
238
+ async function settle(page: Page) {
239
+ await holdMotionStill(page);
240
+ await page.evaluate(async () => document.fonts.ready);
241
+ await page.waitForTimeout(40);
242
+ }
243
+
244
+ async function openSurface(
245
+ page: Page,
246
+ item: AuditCase,
247
+ ): Promise<{surface: Locator; pointer: {x: number; y: number}}> {
248
+ const trigger =
249
+ item.storyId === 'core-contextmenu--pointer-presentation'
250
+ ? page.getByTestId('pointer-context-menu')
251
+ : item.storyId === 'core-contextmenu--bottom-sheet-presentation'
252
+ ? page.getByTestId('bottom-sheet-context-menu')
253
+ : item.triggerText
254
+ ? page.getByText(item.triggerText, {exact: true}).first()
255
+ : null;
256
+ if (trigger === null) {
257
+ throw new Error(`No trigger configured for ${item.key}`);
258
+ }
259
+ await trigger.scrollIntoViewIfNeeded();
260
+ const triggerBox = await trigger.boundingBox();
261
+ if (triggerBox === null) {
262
+ throw new Error(`Trigger has no rendered box for ${item.key}`);
263
+ }
264
+ const pointer = {
265
+ x: triggerBox.x + Math.min(40, triggerBox.width / 2),
266
+ y: triggerBox.y + Math.min(40, triggerBox.height / 2),
267
+ };
268
+ await page.mouse.click(pointer.x, pointer.y, {button: 'right'});
269
+ const surface =
270
+ item.surface === 'dialog'
271
+ ? page.getByRole('dialog').last()
272
+ : item.menuName
273
+ ? page.getByRole('menu', {name: item.menuName}).last()
274
+ : page.getByRole('menu').last();
275
+ await expect(surface).toBeVisible();
276
+ return {surface, pointer};
277
+ }
278
+
279
+ test.beforeAll(async () => {
280
+ fs.rmSync(OUTPUT, {recursive: true, force: true});
281
+ fs.mkdirSync(OUTPUT, {recursive: true});
282
+ checkoutSha = execFileSync('git', ['rev-parse', 'HEAD'], {
283
+ encoding: 'utf8',
284
+ }).trim();
285
+ const expected = process.env.ASTRYX_HEAD_SHA;
286
+ if (expected && expected !== checkoutSha) {
287
+ throw new Error(
288
+ `checkout ${checkoutSha} does not match expected head ${expected}`,
289
+ );
290
+ }
291
+ server = await serveStorybook(
292
+ process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
293
+ );
294
+ const response = await fetch(`${server.origin}/astryx-build-sha.txt`);
295
+ if (!response.ok) {
296
+ throw new Error(`Storybook build has no SHA stamp (${response.status})`);
297
+ }
298
+ storybookSha = (await response.text()).trim();
299
+ if (storybookSha !== checkoutSha) {
300
+ throw new Error(
301
+ `Storybook ${storybookSha} does not match checkout ${checkoutSha}`,
302
+ );
303
+ }
304
+ });
305
+
306
+ test.afterAll(async () => {
307
+ await server?.close();
308
+ });
309
+
310
+ for (const item of cases) {
311
+ test(item.key, async ({browser}) => {
312
+ const context = await browser.newContext({
313
+ viewport: item.viewport,
314
+ colorScheme: item.mode,
315
+ reducedMotion: 'reduce',
316
+ });
317
+ const page = await context.newPage();
318
+ const pageErrors: string[] = [];
319
+ page.on('pageerror', error => pageErrors.push(String(error)));
320
+ await page.goto(storyUrl(item), {waitUntil: 'load'});
321
+ await page.locator('#storybook-root').waitFor();
322
+ const {surface, pointer} = await openSurface(page, item);
323
+ await settle(page);
324
+
325
+ const menuItems = page.locator(
326
+ '[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]',
327
+ );
328
+ if (item.surface === 'menu') {
329
+ await expect(menuItems.first()).toBeVisible();
330
+ } else {
331
+ await expect(surface.getByRole('button').first()).toBeVisible();
332
+ }
333
+ if (item.expectedState === 'disabled') {
334
+ await expect(
335
+ page.locator('[role="menuitem"][aria-disabled="true"]'),
336
+ ).toHaveCount(1);
337
+ }
338
+ if (item.expectedState === 'sections') {
339
+ await expect(page.getByRole('group')).toHaveCount(2);
340
+ }
341
+ if (item.expectedState === 'selectable') {
342
+ await expect(page.getByRole('menuitemcheckbox')).toHaveCount(2);
343
+ await expect(page.getByRole('menuitemradio')).toHaveCount(3);
344
+ await expect(
345
+ page.locator('[role="menuitemradio"][aria-checked="true"]'),
346
+ ).toHaveCount(1);
347
+ }
348
+
349
+ const observed = await surface.evaluate(element => {
350
+ const box = element.getBoundingClientRect();
351
+ return {
352
+ theme: document
353
+ .querySelector('[data-astryx-theme]')
354
+ ?.getAttribute('data-astryx-theme'),
355
+ mode: document.documentElement.getAttribute('data-theme'),
356
+ direction: getComputedStyle(element).direction,
357
+ viewport: {width: innerWidth, height: innerHeight},
358
+ reducedMotion: matchMedia('(prefers-reduced-motion: reduce)').matches,
359
+ horizontalOverflow:
360
+ document.documentElement.scrollWidth > innerWidth + 1,
361
+ fonts: document.fonts.status,
362
+ surfaceRole:
363
+ element.getAttribute('role') ??
364
+ (element instanceof HTMLDialogElement ? 'dialog' : null),
365
+ surfaceName:
366
+ element.getAttribute('aria-label') ??
367
+ element.getAttribute('aria-labelledby'),
368
+ geometry: {x: box.x, y: box.y, width: box.width, height: box.height},
369
+ };
370
+ });
371
+ const geometryPass =
372
+ observed.geometry !== null &&
373
+ observed.geometry.width > 0 &&
374
+ observed.geometry.height > 0;
375
+ let pointerPlacementPass = true;
376
+ if (item.storyId === 'core-contextmenu--pointer-presentation') {
377
+ const surfaceBox = await surface.boundingBox();
378
+ pointerPlacementPass =
379
+ surfaceBox !== null &&
380
+ Math.abs(
381
+ (item.direction === 'rtl'
382
+ ? surfaceBox.x + surfaceBox.width
383
+ : surfaceBox.x) - pointer.x,
384
+ ) <= 24 &&
385
+ Math.abs(surfaceBox.y - pointer.y) <= 24;
386
+ }
387
+
388
+ const png = await page.screenshot({animations: 'disabled', fullPage: true});
389
+ const image = `${item.key}.png`;
390
+ const receipt = {
391
+ schemaVersion: 1,
392
+ expected: {
393
+ build: checkoutSha,
394
+ storyId: item.storyId,
395
+ mode: item.mode,
396
+ direction: item.direction,
397
+ theme: item.theme,
398
+ viewport: item.viewport,
399
+ surface: item.surface,
400
+ state: item.expectedState ?? 'default',
401
+ },
402
+ observed: {
403
+ build: storybookSha,
404
+ ...observed,
405
+ menuItemCount: await menuItems.count(),
406
+ pageErrors,
407
+ },
408
+ image: {
409
+ file: image,
410
+ sha256: createHash('sha256').update(png).digest('hex'),
411
+ width: png.readUInt32BE(16),
412
+ height: png.readUInt32BE(20),
413
+ },
414
+ checks: {geometryPass, pointerPlacementPass},
415
+ passed:
416
+ storybookSha === checkoutSha &&
417
+ pageErrors.length === 0 &&
418
+ observed.theme === item.theme &&
419
+ observed.mode === item.mode &&
420
+ observed.direction === item.direction &&
421
+ observed.viewport.width === item.viewport.width &&
422
+ observed.viewport.height === item.viewport.height &&
423
+ observed.reducedMotion &&
424
+ !observed.horizontalOverflow &&
425
+ observed.fonts === 'loaded' &&
426
+ observed.surfaceRole === item.surface &&
427
+ geometryPass &&
428
+ pointerPlacementPass,
429
+ };
430
+ fs.writeFileSync(path.join(OUTPUT, image), png);
431
+ fs.writeFileSync(
432
+ path.join(OUTPUT, `${item.key}.sensors.json`),
433
+ `${JSON.stringify(receipt, null, 2)}\n`,
434
+ );
435
+ expect(receipt.passed).toBe(true);
436
+ await context.close();
437
+ });
438
+ }
@@ -110,6 +110,52 @@ beforeEach(() => {
110
110
  });
111
111
 
112
112
  describe('Dialog', () => {
113
+ it('restores focus to the opener when content mounts in the open commit', () => {
114
+ function Harness({
115
+ open,
116
+ onOpenChange,
117
+ }: {
118
+ open: boolean;
119
+ onOpenChange: (v: boolean) => void;
120
+ }) {
121
+ return (
122
+ <>
123
+ <button type="button" onClick={() => onOpenChange(true)}>
124
+ Open
125
+ </button>
126
+ <Dialog isOpen={open} onOpenChange={onOpenChange}>
127
+ {open ? (
128
+ <div>
129
+ <DialogHeader title="Review" />
130
+ <p>Body</p>
131
+ </div>
132
+ ) : null}
133
+ </Dialog>
134
+ </>
135
+ );
136
+ }
137
+
138
+ let open = false;
139
+ const setOpen = (v: boolean) => {
140
+ open = v;
141
+ };
142
+ const harness = render(<Harness open={open} onOpenChange={setOpen} />);
143
+ const opener = screen.getByRole('button', {name: 'Open'});
144
+ opener.focus();
145
+
146
+ fireEvent.click(opener);
147
+ harness.rerender(<Harness open={open} onOpenChange={setOpen} />);
148
+
149
+ // The freshly mounted header title is the focused screen reader anchor
150
+ // while the dialog is open...
151
+ expect(document.activeElement).toBe(screen.getByText('Review'));
152
+
153
+ // ...but closing restores the element that opened the dialog, not the
154
+ // (now unmounted) title.
155
+ harness.rerender(<Harness open={false} onOpenChange={setOpen} />);
156
+ expect(document.activeElement).toBe(opener);
157
+ });
158
+
113
159
  it('renders when isOpen is true', () => {
114
160
  render(
115
161
  <Dialog isOpen={true} onOpenChange={() => {}}>
@@ -32,6 +32,7 @@ import {
32
32
  useCallback,
33
33
  useEffect,
34
34
  useId,
35
+ useLayoutEffect,
35
36
  useMemo,
36
37
  useRef,
37
38
  type ReactNode,
@@ -505,12 +506,26 @@ export function Dialog({
505
506
 
506
507
  const mergedDialogRef = useMergedRefs(ref, attachDialog);
507
508
 
508
- // Capture the element that was focused when the dialog opened,
509
- // for directional animation origin and focus restoration on close.
509
+ // Capture the element that was focused when the dialog opened, for
510
+ // directional animation origin and focus restoration on close.
510
511
  const triggerElementRef = useRef<HTMLElement | null>(null);
511
512
 
512
513
  useInteractionModalityTracking();
513
514
 
515
+ // This runs in a layout effect so the capture lands before any descendant's
516
+ // passive mount effect: all layout effects run before any passive effect,
517
+ // while a child's passive effect runs before this parent's passive effect.
518
+ // Content that mounts in the open commit — e.g. a DialogHeader focusing its
519
+ // own title on mount — would otherwise move document.activeElement inside
520
+ // the dialog before the capture ran, and closing would then restore focus
521
+ // to a detached node, stranding the user's focus on <body>.
522
+ useLayoutEffect(() => {
523
+ if (isInline || !isOpen) {
524
+ return;
525
+ }
526
+ triggerElementRef.current = document.activeElement as HTMLElement | null;
527
+ }, [isOpen, isInline]);
528
+
514
529
  // Derive dismissal behavior from purpose
515
530
  const allowEscape = purpose !== 'required';
516
531
  const allowBackdropClick = purpose === 'info';
@@ -526,11 +541,9 @@ export function Dialog({
526
541
  }
527
542
 
528
543
  if (isOpen) {
529
- // Capture the currently focused element as the trigger — used for
530
- // directional animation origin and focus restoration on close.
531
- triggerElementRef.current = document.activeElement as HTMLElement | null;
532
-
533
- // Set directional CSS custom properties before opening
544
+ // Set directional CSS custom properties before opening. The trigger was
545
+ // captured by the layout effect above, before any descendant effect
546
+ // could move focus.
534
547
  const trigger = triggerElementRef.current;
535
548
  if (trigger && trigger !== document.body) {
536
549
  const dir = getDialogDirection(trigger);
@@ -25,18 +25,4 @@ export const DIALOG_MODAL_KNOWN_FAILURES: ReadonlyArray<KnownFailure> = [
25
25
  reason:
26
26
  'This migration records the existing focus-order violation without changing the overlapping Dialog implementation path.',
27
27
  },
28
- {
29
- expectation: 'modal-dialog.focus.restored',
30
- binding: 'Dialog',
31
- state: 'conditional-content-focus-restoration',
32
- evidenceLayer: 'real-browser',
33
- failureEquals:
34
- 'closing the modal dialog did not return focus to its still-available invoker',
35
- standardsReference:
36
- 'Astryx component:Dialog FR4 — closing a native Dialog must return focus to its still-connected invoker when it can receive focus.',
37
- userImpact:
38
- 'When focus-moving content mounts only while the dialog is open, closing can leave the user at the document body instead of the control that opened the task.',
39
- reason:
40
- 'This migration records the existing restoration violation without changing the overlapping Dialog implementation path.',
41
- },
42
28
  ];