@astryxdesign/core 0.5.2-canary.2da7a39 → 0.5.2-canary.2e51213

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 (375) hide show
  1. package/dist/AppShell/AppShell.d.ts +2 -2
  2. package/dist/AppShell/AppShell.d.ts.map +1 -1
  3. package/dist/AppShell/AppShell.js +10 -7
  4. package/dist/Banner/Banner.d.ts +5 -0
  5. package/dist/Banner/Banner.d.ts.map +1 -1
  6. package/dist/Banner/Banner.js +7 -2
  7. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
  8. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  9. package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
  10. package/dist/Carousel/Carousel.d.ts.map +1 -1
  11. package/dist/Carousel/Carousel.js +2 -2
  12. package/dist/Chat/ChatComposer.d.ts +2 -2
  13. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  14. package/dist/Chat/ChatComposer.js +21 -2
  15. package/dist/Chat/ChatToolCalls.d.ts +1 -1
  16. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  17. package/dist/Chat/ChatToolCalls.js +12 -34
  18. package/dist/Chat/useChatNewMessages.js +3 -3
  19. package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
  20. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  21. package/dist/DateTimeInput/DateTimeInput.d.ts +47 -13
  22. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  23. package/dist/DateTimeInput/DateTimeInput.js +269 -162
  24. package/dist/DateTimeInput/NativeDateSegment.d.ts +24 -0
  25. package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -0
  26. package/dist/DateTimeInput/NativeDateSegment.js +235 -0
  27. package/dist/DateTimeInput/NativeTimeSegment.d.ts +30 -0
  28. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -0
  29. package/dist/DateTimeInput/NativeTimeSegment.js +248 -0
  30. package/dist/DateTimeInput/index.d.ts +1 -1
  31. package/dist/DateTimeInput/index.d.ts.map +1 -1
  32. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +95 -0
  33. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -0
  34. package/dist/DateTimeInput/nativePickerSegmentStyles.js +103 -0
  35. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  36. package/dist/DropdownMenu/DropdownMenu.js +2 -4
  37. package/dist/Field/Field.d.ts.map +1 -1
  38. package/dist/Field/Field.js +10 -4
  39. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  40. package/dist/Field/PanelSearchInput.js +3 -5
  41. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  42. package/dist/FieldStatus/FieldStatus.js +4 -2
  43. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  44. package/dist/Layer/useTouchTrigger.js +2 -4
  45. package/dist/Layout/Layout.d.ts +7 -8
  46. package/dist/Layout/Layout.d.ts.map +1 -1
  47. package/dist/Layout/Layout.js +7 -8
  48. package/dist/MultiSelector/MultiSelector.d.ts +11 -1
  49. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  50. package/dist/MultiSelector/MultiSelector.js +89 -45
  51. package/dist/RadioList/RadioListItem.d.ts +30 -5
  52. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  53. package/dist/RadioList/RadioListItem.js +17 -4
  54. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  55. package/dist/Resizable/ResizeHandle.js +102 -44
  56. package/dist/Resizable/index.d.ts +2 -0
  57. package/dist/Resizable/index.d.ts.map +1 -1
  58. package/dist/Resizable/index.js +1 -0
  59. package/dist/Resizable/useResizable.d.ts +89 -8
  60. package/dist/Resizable/useResizable.d.ts.map +1 -1
  61. package/dist/Resizable/useResizable.js +521 -38
  62. package/dist/Resizable/utils.d.ts +35 -0
  63. package/dist/Resizable/utils.d.ts.map +1 -0
  64. package/dist/Resizable/utils.js +27 -0
  65. package/dist/Selector/Selector.d.ts +10 -0
  66. package/dist/Selector/Selector.d.ts.map +1 -1
  67. package/dist/Selector/Selector.js +105 -57
  68. package/dist/Selector/useSelectorPresentation.d.ts +1 -0
  69. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  70. package/dist/Selector/useSelectorPresentation.js +17 -2
  71. package/dist/Slider/Slider.d.ts.map +1 -1
  72. package/dist/Slider/Slider.js +3 -5
  73. package/dist/Spinner/Spinner.d.ts.map +1 -1
  74. package/dist/Spinner/Spinner.js +9 -10
  75. package/dist/Stepper/Step.d.ts +2 -1
  76. package/dist/Stepper/Step.d.ts.map +1 -1
  77. package/dist/Stepper/Step.js +75 -11
  78. package/dist/Stepper/Stepper.d.ts.map +1 -1
  79. package/dist/Stepper/Stepper.js +1 -0
  80. package/dist/TabList/TabList.d.ts.map +1 -1
  81. package/dist/TabList/TabList.js +2 -3
  82. package/dist/Table/index.d.ts +16 -1
  83. package/dist/Table/index.d.ts.map +1 -1
  84. package/dist/Table/index.js +4 -0
  85. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  86. package/dist/Table/plugins/columnResize/useTableColumnResize.js +8 -9
  87. package/dist/Table/plugins/rowStatus/index.d.ts +1 -1
  88. package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -1
  89. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +11 -30
  90. package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
  91. package/dist/Table/plugins/rowStatus/useTableRowStatus.js +108 -62
  92. package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
  93. package/dist/Table/plugins/sortable/useTableSortable.js +9 -1
  94. package/dist/Text/useTruncation.d.ts +1 -1
  95. package/dist/Text/useTruncation.d.ts.map +1 -1
  96. package/dist/Text/useTruncation.js +8 -7
  97. package/dist/TimeInput/TimeInput.d.ts +16 -1
  98. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  99. package/dist/TimeInput/TimeInput.js +98 -60
  100. package/dist/TimeInput/index.d.ts +1 -1
  101. package/dist/TimeInput/index.d.ts.map +1 -1
  102. package/dist/Timestamp/Timestamp.d.ts +2 -2
  103. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  104. package/dist/Timestamp/Timestamp.js +4 -145
  105. package/dist/Timestamp/formatRelativeTime.d.ts +20 -0
  106. package/dist/Timestamp/formatRelativeTime.d.ts.map +1 -0
  107. package/dist/Timestamp/formatRelativeTime.js +81 -0
  108. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  109. package/dist/Toast/ToastViewport.js +125 -77
  110. package/dist/Tokenizer/Tokenizer.d.ts +0 -38
  111. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  112. package/dist/Tokenizer/Tokenizer.js +94 -26
  113. package/dist/Tokenizer/useEndLaneReserve.d.ts +31 -0
  114. package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
  115. package/dist/Tokenizer/useEndLaneReserve.js +136 -0
  116. package/dist/Tooltip/useTooltip.d.ts +1 -1
  117. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  118. package/dist/Tooltip/useTooltip.js +53 -42
  119. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  120. package/dist/Typeahead/BaseTypeahead.js +85 -30
  121. package/dist/Typeahead/Typeahead.d.ts +0 -21
  122. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  123. package/dist/Typeahead/Typeahead.js +108 -67
  124. package/dist/Typeahead/busyIndicatorLane.d.ts +62 -0
  125. package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
  126. package/dist/Typeahead/busyIndicatorLane.js +98 -0
  127. package/dist/astryx.css +25 -7
  128. package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
  129. package/dist/hooks/useFocusReturnVisibility.js +3 -5
  130. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
  131. package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
  132. package/dist/hooks/useOverflow.js +11 -11
  133. package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
  134. package/dist/hooks/useScrollOverflow.js +7 -4
  135. package/dist/theme/defineTheme.d.ts +13 -0
  136. package/dist/theme/defineTheme.d.ts.map +1 -1
  137. package/dist/theme/defineTheme.js +7 -0
  138. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  139. package/dist/theme/generateThemeRules.js +1 -1
  140. package/dist/theme/localTokens.d.ts +18 -0
  141. package/dist/theme/localTokens.d.ts.map +1 -0
  142. package/dist/theme/localTokens.js +162 -0
  143. package/dist/utils/interactionModality.d.ts +6 -28
  144. package/dist/utils/interactionModality.d.ts.map +1 -1
  145. package/dist/utils/interactionModality.js +72 -37
  146. package/dist/utils/sharedResizeObserver.d.ts +17 -9
  147. package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
  148. package/dist/utils/sharedResizeObserver.js +54 -12
  149. package/locales/en.json +8 -0
  150. package/locales/pseudo.json +6 -0
  151. package/package.json +7 -2
  152. package/src/AlertDialog/useImperativeAlertDialog.test.tsx +163 -0
  153. package/src/AppShell/AppShell.doc.mjs +4 -3
  154. package/src/AppShell/AppShell.test.tsx +21 -0
  155. package/src/AppShell/AppShell.tsx +12 -7
  156. package/src/Banner/Banner.doc.mjs +5 -1
  157. package/src/Banner/Banner.tsx +12 -1
  158. package/src/BottomSheet/BottomSheet.doc.mjs +31 -0
  159. package/src/BottomSheet/BottomSheet.spec.md +178 -0
  160. package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
  161. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
  162. package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
  163. package/src/Button/Button.doc.mjs +56 -0
  164. package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
  165. package/src/Calendar/hooks/useCalendarConstraints.test.ts +153 -0
  166. package/src/Calendar/hooks/useCalendarDays.test.ts +265 -0
  167. package/src/Calendar/hooks/useCalendarNavigation.test.ts +252 -0
  168. package/src/Carousel/Carousel.test.tsx +83 -0
  169. package/src/Carousel/Carousel.tsx +8 -2
  170. package/src/Chat/ChatComposer.doc.mjs +7 -4
  171. package/src/Chat/ChatComposer.test.tsx +84 -2
  172. package/src/Chat/ChatComposer.tsx +45 -3
  173. package/src/Chat/ChatSendButton.test.tsx +189 -0
  174. package/src/Chat/ChatToolCalls.doc.mjs +1 -1
  175. package/src/Chat/ChatToolCalls.test.tsx +33 -1
  176. package/src/Chat/ChatToolCalls.tsx +13 -34
  177. package/src/Chat/useChatNewMessages.ts +3 -3
  178. package/src/Chat/useChatPasteAsToken.test.ts +191 -0
  179. package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
  180. package/src/CheckboxList/CheckboxList.spec.md +215 -0
  181. package/src/CheckboxList/CheckboxList.test.tsx +45 -0
  182. package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
  183. package/src/CheckboxList/CheckboxListItem.tsx +5 -3
  184. package/src/Collapsible/useCollapsible.test.tsx +236 -0
  185. package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
  186. package/src/CommandPalette/CommandPalette.spec.md +224 -0
  187. package/src/CommandPalette/CommandPaletteEmpty.test.tsx +101 -0
  188. package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
  189. package/src/ComplexSelector/ComplexSelector.spec.md +190 -0
  190. package/src/ContextMenu/ContextMenu.doc.mjs +48 -0
  191. package/src/ContextMenu/ContextMenu.spec.md +207 -0
  192. package/src/DateTimeInput/DateTimeInput.doc.mjs +43 -23
  193. package/src/DateTimeInput/DateTimeInput.tsx +388 -181
  194. package/src/DateTimeInput/DateTimeInputTouch.test.tsx +10 -2
  195. package/src/DateTimeInput/NativeDateSegment.tsx +308 -0
  196. package/src/DateTimeInput/NativePickerSegments.test.tsx +626 -0
  197. package/src/DateTimeInput/NativeTimeSegment.tsx +331 -0
  198. package/src/DateTimeInput/index.ts +1 -0
  199. package/src/DateTimeInput/nativePickerSegmentStyles.ts +120 -0
  200. package/src/Divider/Divider.doc.mjs +24 -0
  201. package/src/Divider/Divider.spec.md +157 -0
  202. package/src/DropdownMenu/DropdownMenu.doc.mjs +104 -0
  203. package/src/DropdownMenu/DropdownMenu.spec.md +246 -0
  204. package/src/DropdownMenu/DropdownMenu.tsx +2 -4
  205. package/src/Field/Field.doc.mjs +1 -0
  206. package/src/Field/Field.test.tsx +39 -0
  207. package/src/Field/Field.tsx +18 -1
  208. package/src/Field/InputClearButton.test.tsx +68 -6
  209. package/src/Field/PanelSearchInput.tsx +3 -5
  210. package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
  211. package/src/FieldStatus/FieldStatus.spec.md +213 -0
  212. package/src/FieldStatus/FieldStatus.test.tsx +17 -0
  213. package/src/FieldStatus/FieldStatus.tsx +7 -2
  214. package/src/Grid/Grid.doc.mjs +19 -0
  215. package/src/Grid/Grid.spec.md +162 -0
  216. package/src/Icon/Icon.doc.mjs +196 -48
  217. package/src/Icon/Icon.spec.md +192 -0
  218. package/src/IconButton/IconButton.doc.mjs +38 -0
  219. package/src/Kbd/Kbd.doc.mjs +18 -0
  220. package/src/Kbd/Kbd.spec.md +142 -0
  221. package/src/Layer/useTouchTrigger.ts +2 -4
  222. package/src/Layout/Layout.doc.mjs +57 -17
  223. package/src/Layout/Layout.spec.md +235 -0
  224. package/src/Layout/Layout.test.tsx +1 -1
  225. package/src/Layout/Layout.tsx +7 -8
  226. package/src/Layout/LayoutHeader.doc.mjs +9 -0
  227. package/src/Layout/LayoutPanel.doc.mjs +4 -3
  228. package/src/Lightbox/Lightbox.doc.mjs +149 -33
  229. package/src/Lightbox/Lightbox.spec.md +198 -0
  230. package/src/Lightbox/useLightbox.test.tsx +263 -0
  231. package/src/Markdown/Markdown.doc.mjs +60 -0
  232. package/src/Markdown/Markdown.spec.md +207 -0
  233. package/src/MobileNav/MobileNav.doc.mjs +140 -32
  234. package/src/MobileNav/MobileNav.spec.md +209 -0
  235. package/src/MoreMenu/MoreMenu.doc.mjs +42 -0
  236. package/src/MoreMenu/MoreMenu.spec.md +222 -0
  237. package/src/MultiSelector/MultiSelector.doc.mjs +124 -1
  238. package/src/MultiSelector/MultiSelector.spec.md +293 -0
  239. package/src/MultiSelector/MultiSelector.test.tsx +305 -2
  240. package/src/MultiSelector/MultiSelector.tsx +124 -55
  241. package/src/NavIcon/NavIcon.doc.mjs +17 -0
  242. package/src/NavIcon/NavIcon.spec.md +134 -0
  243. package/src/NavMenu/NavHeadingMenu.spec.md +210 -0
  244. package/src/NavMenu/NavMenu.doc.mjs +37 -0
  245. package/src/Outline/Outline.doc.mjs +35 -0
  246. package/src/Outline/Outline.spec.md +162 -0
  247. package/src/OverflowList/OverflowList.doc.mjs +24 -0
  248. package/src/OverflowList/OverflowList.spec.md +157 -0
  249. package/src/Pagination/Pagination.doc.mjs +74 -0
  250. package/src/Pagination/Pagination.spec.md +226 -0
  251. package/src/Popover/Popover.doc.mjs +264 -65
  252. package/src/Popover/Popover.spec.md +421 -0
  253. package/src/Popover/usePopover.doc.mjs +208 -33
  254. package/src/PowerSearch/PowerSearch.spec.md +291 -0
  255. package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +253 -0
  256. package/src/PowerSearch/PowerSearchToken.test.tsx +228 -0
  257. package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
  258. package/src/ProgressBar/ProgressBar.spec.md +261 -0
  259. package/src/RadioList/RadioList.test.tsx +136 -2
  260. package/src/RadioList/RadioListItem.doc.mjs +30 -11
  261. package/src/RadioList/RadioListItem.tsx +44 -8
  262. package/src/Resizable/Resizable.doc.mjs +130 -24
  263. package/src/Resizable/Resizable.spec.md +246 -0
  264. package/src/Resizable/ResizeHandle.test.tsx +177 -56
  265. package/src/Resizable/ResizeHandle.tsx +128 -45
  266. package/src/Resizable/index.ts +2 -0
  267. package/src/Resizable/shippedDirections.test.ts +462 -0
  268. package/src/Resizable/useResizable.doc.mjs +124 -29
  269. package/src/Resizable/useResizable.test.ts +1277 -3
  270. package/src/Resizable/useResizable.ts +760 -48
  271. package/src/Resizable/utils.test.ts +74 -0
  272. package/src/Resizable/utils.ts +35 -0
  273. package/src/Section/Section.doc.mjs +17 -0
  274. package/src/Section/Section.spec.md +139 -0
  275. package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
  276. package/src/SegmentedControl/SegmentedControl.spec.md +152 -0
  277. package/src/Selector/Selector.doc.mjs +133 -97
  278. package/src/Selector/Selector.spec.md +300 -0
  279. package/src/Selector/Selector.test.tsx +318 -1
  280. package/src/Selector/Selector.tsx +127 -60
  281. package/src/Selector/useSelectorPresentation.ts +24 -4
  282. package/src/SideNav/SideNav.test.tsx +3 -3
  283. package/src/SideNav/SideNavCollapseButton.doc.mjs +8 -0
  284. package/src/SideNav/SideNavItem.doc.mjs +1 -1
  285. package/src/Skeleton/Skeleton.doc.mjs +12 -0
  286. package/src/Skeleton/Skeleton.spec.md +127 -0
  287. package/src/Slider/Slider.doc.mjs +184 -30
  288. package/src/Slider/Slider.spec.md +224 -0
  289. package/src/Slider/Slider.tsx +2 -5
  290. package/src/Spinner/Spinner.doc.mjs +5 -5
  291. package/src/Spinner/Spinner.test.tsx +32 -7
  292. package/src/Spinner/Spinner.tsx +46 -14
  293. package/src/Stack/Stack.doc.mjs +22 -0
  294. package/src/Stack/Stack.spec.md +155 -0
  295. package/src/StatusDot/StatusDot.doc.mjs +17 -0
  296. package/src/StatusDot/StatusDot.spec.md +138 -0
  297. package/src/Stepper/Step.doc.mjs +1 -1
  298. package/src/Stepper/Step.tsx +118 -5
  299. package/src/Stepper/Stepper.doc.mjs +51 -1
  300. package/src/Stepper/Stepper.spec.md +245 -0
  301. package/src/Stepper/Stepper.test.tsx +315 -0
  302. package/src/Stepper/Stepper.tsx +8 -0
  303. package/src/Switch/Switch.doc.mjs +40 -0
  304. package/src/Switch/Switch.spec.md +175 -0
  305. package/src/TabList/TabList.tsx +2 -3
  306. package/src/Table/Table.doc.mjs +102 -24
  307. package/src/Table/Table.perf.test.tsx +51 -1
  308. package/src/Table/Table.spec.md +325 -0
  309. package/src/Table/TableHeaderCell.test.tsx +291 -0
  310. package/src/Table/index.ts +19 -4
  311. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -12
  312. package/src/Table/plugins/filtering/useTableFilterState.test.tsx +143 -0
  313. package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +2 -1
  314. package/src/Table/plugins/rowStatus/index.ts +1 -4
  315. package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +92 -0
  316. package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
  317. package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +431 -56
  318. package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +155 -84
  319. package/src/Table/plugins/sortable/useTableSortable.test.tsx +72 -0
  320. package/src/Table/plugins/sortable/useTableSortable.tsx +18 -1
  321. package/src/Table/useTableGroupedRows.doc.mjs +2 -2
  322. package/src/Table/useTableRowStatus.doc.mjs +5 -5
  323. package/src/Text/Text.doc.mjs +190 -43
  324. package/src/Text/Text.spec.md +206 -0
  325. package/src/Text/useTruncation.ts +8 -7
  326. package/src/TextArea/TextArea.doc.mjs +255 -45
  327. package/src/TextArea/TextArea.spec.md +205 -0
  328. package/src/TimeInput/NativeTimeInput.test.tsx +269 -0
  329. package/src/TimeInput/TimeInput.doc.mjs +47 -23
  330. package/src/TimeInput/TimeInput.tsx +109 -50
  331. package/src/TimeInput/index.ts +1 -0
  332. package/src/Timestamp/Timestamp.doc.mjs +2 -2
  333. package/src/Timestamp/Timestamp.test.tsx +75 -3
  334. package/src/Timestamp/Timestamp.tsx +7 -153
  335. package/src/Timestamp/formatRelativeTime.ts +96 -0
  336. package/src/Toast/ToastViewport.test.tsx +194 -0
  337. package/src/Toast/ToastViewport.tsx +136 -58
  338. package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
  339. package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
  340. package/src/Tokenizer/Tokenizer.spec.md +293 -0
  341. package/src/Tokenizer/Tokenizer.test.tsx +335 -1
  342. package/src/Tokenizer/Tokenizer.tsx +129 -46
  343. package/src/Tokenizer/useEndLaneReserve.ts +146 -0
  344. package/src/Toolbar/Toolbar.doc.mjs +19 -0
  345. package/src/Toolbar/Toolbar.spec.md +174 -0
  346. package/src/Tooltip/Tooltip.doc.mjs +17 -0
  347. package/src/Tooltip/Tooltip.spec.md +142 -0
  348. package/src/Tooltip/Tooltip.test.tsx +21 -1
  349. package/src/Tooltip/useTooltip.test.tsx +318 -0
  350. package/src/Tooltip/useTooltip.tsx +60 -39
  351. package/src/TreeList/TreeList.doc.mjs +58 -0
  352. package/src/TreeList/TreeList.spec.md +224 -0
  353. package/src/Typeahead/BaseTypeahead.tsx +96 -25
  354. package/src/Typeahead/Typeahead.doc.mjs +89 -1
  355. package/src/Typeahead/Typeahead.spec.md +257 -0
  356. package/src/Typeahead/Typeahead.test.tsx +502 -1
  357. package/src/Typeahead/Typeahead.tsx +187 -69
  358. package/src/Typeahead/TypeaheadItem.test.tsx +93 -2
  359. package/src/Typeahead/busyIndicatorLane.tsx +109 -0
  360. package/src/__tests__/stylexDeclarations.ts +51 -0
  361. package/src/hooks/useFocusReturnVisibility.ts +3 -5
  362. package/src/hooks/useOverflow.ts +11 -11
  363. package/src/hooks/useScrollLock.test.ts +103 -0
  364. package/src/hooks/useScrollOverflow.ts +7 -4
  365. package/src/i18n/useTranslator.test.tsx +197 -0
  366. package/src/theme/defineTheme.test.ts +227 -0
  367. package/src/theme/defineTheme.ts +30 -0
  368. package/src/theme/derivedVarRegistry.test.ts +6 -0
  369. package/src/theme/generateThemeRules.ts +4 -1
  370. package/src/theme/localTokens.ts +272 -0
  371. package/src/theme/themingTargets.test.ts +126 -28
  372. package/src/utils/interactionModality.test.ts +83 -0
  373. package/src/utils/interactionModality.ts +88 -36
  374. package/src/utils/sharedResizeObserver.test.ts +124 -5
  375. package/src/utils/sharedResizeObserver.ts +60 -14
@@ -0,0 +1,421 @@
1
+ ---
2
+ schema_version: 3
3
+ template_version: 3
4
+ kind: component
5
+ id: component:Popover
6
+ authority: current
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: cixzhang
10
+ approved_at: 2026-08-31
11
+ owners: [cixzhang]
12
+ review_triggers: [public-api, behavior, layout, theming, accessibility]
13
+ verified_by:
14
+ [
15
+ packages/core/src/Popover/Popover.test.tsx,
16
+ packages/core/src/Popover/Popover.doc.mjs,
17
+ packages/core/src/Popover/usePopover.doc.mjs,
18
+ packages/core/src/hooks/useFocusTrap.test.tsx,
19
+ packages/cli/foundation/discovery/theming-targets.mjs,
20
+ packages/cli/foundation/discovery/theming-targets.test.mjs,
21
+ scripts/check-knowledge.mjs,
22
+ ]
23
+ modules: []
24
+ families: [family:overlay-dismissal]
25
+ design_specs: []
26
+ architecture:
27
+ [
28
+ architecture:component-theming-surface,
29
+ architecture:interaction-modality,
30
+ architecture:layer-runtime,
31
+ architecture:public-component-api,
32
+ ]
33
+ contributing: []
34
+ system_specs: []
35
+ ---
36
+
37
+ # Popover component contract
38
+
39
+ ## Intent
40
+
41
+ Popover presents interactive, caller-supplied content in an anchored top-layer
42
+ surface. The component owns the standard trigger-to-surface composition;
43
+ `usePopover` exposes the same semantic lifecycle, focus containment, dismissal,
44
+ and rendering contract for custom compositions.
45
+
46
+ This contract records the behavior present after
47
+ [PR #5373](https://github.com/facebook/astryx/pull/5373) and the Popover target
48
+ direction settled by Cindy Zhang on 2026-08-31. It does not change runtime
49
+ behavior, public API, emitted classes, or release status. Consumer syntax and
50
+ complete signatures remain owned by `Popover.doc.mjs` and
51
+ `usePopover.doc.mjs`; automatic canonical-target emission and compatibility
52
+ removal require separately reviewed runtime work.
53
+
54
+ ## Compatibility and migration
55
+
56
+ - Released default preserved: `yes`
57
+ - Compatibility class: documentation-only target ownership clarification;
58
+ runtime, DOM, styling, emitted classes, and public API are unchanged
59
+ - Canonical target: `popover` owns the broad painted-surface contract for
60
+ `<Popover>` and public `usePopover` compositions
61
+ - Deprecated alias: `popover-surface` remains emitted so existing themes keep
62
+ working during a documented migration window; it is not a second anatomy part
63
+ or equal durable owner
64
+ - Composed components: component-specific surface targets such as
65
+ `selector-popup` and `multi-selector-popup` remain authoritative refinements;
66
+ compatibility output may remain underneath until migration
67
+ - New hook consumers: a direct `usePopover` composition that needs its own theme
68
+ reachability provides and documents an owned `surfaceTarget`; it does not
69
+ create a new dependency on `popover-surface`
70
+ - Migration decision: target ownership is settled; automatic `popover` emission
71
+ for every painted hook surface and eventual alias removal ship only through
72
+ separately reviewed runtime changes
73
+
74
+ The implementation migration must preserve `popover-surface` themes until its
75
+ announced removal window. Implementation and removal each update consumer
76
+ migration guidance, target inventory, focused tests, and changelog or release
77
+ documentation; this documentation-only PR does none of those runtime steps.
78
+
79
+ ## Ownership boundary
80
+
81
+ **Owns**
82
+
83
+ - The standard trigger or referenced-anchor composition, the painted Popover
84
+ surface, the canonical broad `popover` theme target for that surface, and the
85
+ slot that renders caller-supplied content inside it.
86
+ - The public `usePopover` semantic contract: visibility operations, trigger
87
+ bindings, surface rendering, dialog semantics, focus containment, and
88
+ lifecycle notifications.
89
+ - Popover-specific focus destination selection, viewport fitting, safe-area
90
+ gutters, match-trigger sizing, conditional internal scrolling, and the
91
+ measurement lifecycle needed to support them.
92
+ - The current fallback close control appended by the hook.
93
+
94
+ **Does not own / non-goals**
95
+
96
+ - Trigger presentation and caller content presentation — caller-owned.
97
+ - Component-specific surface refinement targets — owned and documented by the
98
+ composed component; Popover supplies only the shared baseline target contract.
99
+ - Generic top-layer hosting, native popover lifecycle reconciliation, anchor
100
+ positioning, portal/context selection, and same-gesture reopen protection —
101
+ owned by `architecture:layer-runtime`.
102
+ - Shared Escape and platform-close ordering — owned by
103
+ `family:overlay-dismissal`.
104
+ - The shared focus-trap algorithm outside Popover-specific destination choice —
105
+ owned by `useFocusTrap`.
106
+ - Hover previews and brief helper text — owned by HoverCard and Tooltip.
107
+
108
+ ## Public surface and package boundary
109
+
110
+ The installable root package and `@astryxdesign/core/Popover` subpath expose the
111
+ full Popover public surface. The backward-compatible Layer entry point re-exports
112
+ `Popover`, `usePopover`, `UsePopoverOptions`, `UsePopoverReturn`, and
113
+ `PopoverProps`; `PopoverTriggerRenderProps` is exposed through the Popover package
114
+ surface, not the Layer entry point. There is no installable
115
+ `Popover/usePopover` implementation subpath.
116
+
117
+ The source-level internal hook is a package implementation seam used by Popover
118
+ and related presentation components. Its dismissal guard and wider focus-opening
119
+ controls are not installable consumer API. Source-file exports do not promote
120
+ those concepts into the package contract.
121
+
122
+ ## Public concepts
123
+
124
+ | Concept | Closed values or states | Meaning | Availability | Default | Owner | Stability | Invalid or unsupported behavior |
125
+ | ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
126
+ | Trigger composition | Wrapped trigger, render-prop trigger, or referenced anchor | Supplies the anchor and the control that opens or closes the standard component | Popover | Wrapped trigger when children are supplied | `component:Popover` | Current public behavior | A referenced or wrapped anchor without a button or button role warns in development and receives no trigger handler; it does not throw. |
127
+ | Visibility ownership | Uncontrolled or externally controlled | Chooses whether Popover stores visibility or synchronizes to caller state | Popover | Uncontrolled | `component:Popover` | Current public behavior | Controlled changes are synchronized through show/hide; dismissal requests are reported to the caller rather than redefining the external source of truth. |
128
+ | Popup semantics | Dialog or neutral wrapper | Exposes dialog semantics or lets child menu/listbox semantics own the popup | Popover and hook | Dialog | `component:Popover` | Current public behavior | A dialog without a label warns in development. Neutral mode omits dialog role and modal semantics. |
129
+ | Focus entry | Automatic or caller-preserved | Moves focus according to the matrix below or leaves current focus unchanged | Popover and hook | Automatic | `component:Popover` | Current public behavior | A request to skip autofocus affects that opening only. |
130
+ | Dismissal | Outside/Escape enabled or disabled within native constraints | Controls light dismiss and explicit Escape participation | Popover and hook | Both enabled | `component:Popover`; `family:overlay-dismissal` owns Escape/platform-close ordering | Current public behavior | Disabling Escape alone cannot override the native Escape behavior of an auto popover; explicit-dismiss behavior requires light dismiss to be disabled too. |
131
+ | Surface treatment | Default surface or caller-owned treatment | Applies the shared painted surface and optional consumer styling | Popover and hook | Default surface | `component:Popover` | Current public behavior | Custom styling does not change lifecycle, focus, or dismissal semantics. |
132
+ | Surface target ownership | Shared baseline or component-specific refinement | Assigns `popover` as the broad surface owner and lets a composed component add its own target on that same element | Popover and hook | `popover` baseline; no component-specific refinement | `component:Popover`; the composed component owns its refinement target | Accepted contract; runtime alignment pending | `popover-surface` is compatibility output, not a new target for consumers or a second anatomy owner. |
133
+ | Placement and fit | Logical placement/alignment plus preferred width | Positions the anchor surface and constrains it to available space | Popover and hook renderer | Below/start; Popover matches trigger minimum width when no width is supplied | `component:Popover` above `architecture:layer-runtime` | Current public behavior | Preferred width and trigger matching remain capped by viewport and safe-area availability. |
134
+
135
+ ### Public `usePopover` semantic inputs
136
+
137
+ Consumer syntax, exact names, and types remain in `usePopover.doc.mjs`; this
138
+ table owns their semantic effect.
139
+
140
+ | Input concept | Default | Effect and lifetime | Invalid or unsupported behavior |
141
+ | --------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
142
+ | Show and hide notifications | Absent | Fire after the hook updates its visibility for an imperative or reconciled browser transition. They remain active for the mounted hook instance. | No callback is fired when no transition occurs. Callers own any focus return they add in a hide notification. |
143
+ | Surface styling | No consumer override | Merges consumer StyleX, class, and inline styles onto the painted surface for every rendered lifetime. | Styling cannot move ownership to the positioned outer layer; positioning styles belong to the renderer's layer props. |
144
+ | Light and Escape dismissal | Enabled | Escape dismissal registers through the focus trap when enabled; outside light dismiss uses native `popover="auto"` and is not shared-stack coordinated. | Escape disablement is only complete when native light dismiss is also disabled. |
145
+ | Automatic focus | Enabled | Runs once for each successful open unless that opening requests preservation. | If no genuine content control exists, dialog mode falls back to the surface container. |
146
+ | Fallback close control and label | Included; “Close popover” | Appends an end-of-trap close control for each rendered surface. | When omitted, the hook does not synthesize another close affordance. |
147
+ | Popup role, label, and modality | Dialog, modal, no implicit label | Stamps semantics on the painted surface for its rendered lifetime. | Neutral role suppresses dialog and modal semantics. Missing dialog label warns in development rather than throwing. |
148
+ | Default surface | Enabled | Applies the shared background, radius, and elevation treatment while rendered. | Turning it off delegates painting to caller content but does not turn `usePopover` into a different lifecycle primitive. |
149
+ | Optional component surface target | No component-specific refinement | Adds a component-owned refinement target beside the canonical `popover` target on the same rendered surface. New direct hook consumers provide and document one only when they need distinct theme reachability. | `surfaceTarget` does not create another surface or owner. Do not pass or depend on deprecated `popover-surface`. |
150
+
151
+ ### Public `usePopover` semantic outputs
152
+
153
+ | Output concept | Meaning and lifetime |
154
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
155
+ | Trigger binding | A ref binding establishes the anchor while attached; ARIA trigger state tracks the current role and open state; a stable anchor identifier supports advanced composition. Detaching the trigger removes its anchor association. |
156
+ | Visibility operations | `show`, `hide`, and `toggle` are the canonical operations for the mounted hook instance. Show may preserve current focus for one opening; hide and toggle add no separate caller-owned focus destination. |
157
+ | Open state | Reflects the hook's reconciled visibility. Browser-initiated close is observed on the queued native toggle event, so DOM visibility may lead React state briefly. |
158
+ | Surface binding | A content ref identifies the focus-trap surface while mounted. |
159
+ | Renderer | Produces the positioned layer and painted surface around caller content, including focus containment and the optional fallback close control. The renderer must remain in the React tree for the surface to exist. |
160
+ | Surface identifier | A stable identifier connects the trigger's control relationship to the rendered surface for the hook instance. |
161
+
162
+ ### Side effects and lifetime
163
+
164
+ - Attaching the trigger ref assigns and removes the CSS anchor name used by the
165
+ Layer runtime.
166
+ - Successful visibility operations call the browser popover methods when
167
+ available, update hook state, and invoke the corresponding lifecycle
168
+ notification. Native close events reconcile back into that same state model.
169
+ - The default context layer keeps its mounted host while closed after initial
170
+ resolution; open state, not host existence, controls visibility. Lazy mounting
171
+ remains a Layer-level option rather than a separate Popover contract.
172
+ - Popover component trigger handlers and ARIA state exist only while the trigger
173
+ is mounted and enabled. Disabling Popover ignores its trigger interaction; it
174
+ does not disable the caller's trigger element.
175
+
176
+ ## Behavioral and layout contract
177
+
178
+ | ID | Invariant | Basis | Acceptance and implementation state |
179
+ | --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
180
+ | FR1 | Popover and public `usePopover` expose one visibility lifecycle with canonical show, hide, and toggle operations. Options that refine opening remain part of that operation; an internal need does not create a durable parallel toggle concept. | Current public package surface plus owner direction on 2026-08-31 | Direction settled; current internal helper naming remains a verification gap, not a second API decision |
181
+ | FR2 | Focus destination is derived from popup role, activation style, content, and autofocus policy. Callers do not choose a public focus target. | PR #5373, current source, and current tests | Settled current component behavior |
182
+ | FR3 | The preferred surface size is capped to logical viewport and safe-area availability before overflow is enabled. | PR #5373, current source, tests, and Storybook fixtures | Verified in unit/style evidence; real rendered viewport evidence remains a gap |
183
+ | FR4 | Popover enables internal scrolling only after measured overflow exceeds the current tolerance. Fitting content does not become a scroll container. | PR #5373 and current tests | Verified current behavior |
184
+ | FR5 | Overflow signals while open coalesce into at most one measurement per animation frame, and Popover owns no measurement observers while closed. | PR #5373 and current tests | Verified current resource behavior |
185
+ | FR6 | Component anatomy contains the caller trigger and content, one painted Popover surface, and the optional fallback close control. Popover owns no Header, Body, or separate shared-hook surface part. | Current source, docs target inventory, and tests | Accepted anatomy; stale consumer anatomy corrected by this contract |
186
+ | FR7 | The painted surface has one broad canonical target, `popover`. `popover-surface` is a deprecated compatibility alias on that same part; composed components may add one authoritative component-specific refinement target. | Owner direction on 2026-08-31 plus current target inventory | Accepted semantic contract; automatic hook-wide emission and compatibility removal remain separately reviewed runtime work |
187
+
188
+ ### Allowed variation
189
+
190
+ - **AV1 — Trigger composition.** Wrapped, render-prop, and referenced-anchor
191
+ modes may attach the same semantic trigger behavior without changing the
192
+ surface contract.
193
+ - **AV2 — Popup semantics.** Dialog mode may focus the dialog container;
194
+ role-neutral popups let their child role and content focus model remain
195
+ exposed.
196
+ - **AV3 — Surface treatment.** The hook may omit its default paint or add a
197
+ component-owned refinement target while preserving the canonical `popover`
198
+ ownership, lifecycle, focus containment, and dismissal model.
199
+ - **AV4 — Placement.** Logical placement, alignment, preferred width, and
200
+ available viewport size may change geometry without changing the fit and
201
+ overflow precedence below.
202
+
203
+ ### Representative focus and dismissal states
204
+
205
+ | State | Required invariant | Allowed variation |
206
+ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
207
+ | Pointer or touch activation of dialog Popover | Initial focus moves to the labeled dialog container so an action does not appear preselected. | The trigger and content may vary. |
208
+ | Keyboard or AT-style activation of dialog Popover | Initial focus moves to the first genuine content control; when none exists, it moves to the dialog container. | Activation with absent or zero event detail follows this path. Named AT announcement remains unverified. |
209
+ | Read-only dialog | The dialog container receives initial focus; the fallback close control remains reachable by Tab but is not selected as initial content. | Caller content may contain no tabbable control. |
210
+ | Neutral-role popup | The neutral wrapper is not selected as a dialog focus target; automatic entry prefers genuine content focus, or callers may disable autofocus for trigger-retained patterns. | Child menu, listbox, or other semantics own their focus model. |
211
+ | Automatic focus disabled | Opening does not move focus. | May be persistent configuration or a one-opening show preference. |
212
+ | Controlled open | External open state invokes the no-activation opening path: first genuine content control, then dialog-container fallback. | The caller remains the visibility source of truth. |
213
+ | Tab from a focused container | Focus enters the first tabbable descendant. | If none exists, focus remains inside. |
214
+ | Shift+Tab from a focused container | Focus enters the last tabbable descendant. | If none exists, focus remains inside. |
215
+ | Escape | The topmost eligible Popover closes according to shared dismissal policy. | Explicit-dismiss surfaces may disable both light and Escape dismissal. |
216
+ | Close after focus entered the popup | Focus returns to the trigger when removal would otherwise strand focus. | A caller may additionally own focus return through its hide notification. |
217
+
218
+ ### Transformation and precedence order
219
+
220
+ - **ORD1 — Visibility operation.** `toggle` selects the existing `show` or `hide`
221
+ transition; it is not a second lifecycle. Opening preferences refine `show`.
222
+ Popover derives any internal focus destination before invoking that operation.
223
+ - **ORD2 — Preferred inline size.** An explicit width wins over trigger matching.
224
+ Without explicit width, Popover prefers trigger minimum width. Either preferred
225
+ size remains capped by available viewport and safe-area space.
226
+ - **ORD3 — Viewport fit.** Logical placement and alignment select the applicable
227
+ safe-area gutters; the positioned layer and painted surface are capped before
228
+ overflow state is evaluated.
229
+ - **ORD4 — Conditional scroll.** Measured overflow greater than 1 px enables
230
+ internal scrolling and overscroll containment; fitting content leaves both
231
+ disabled.
232
+
233
+ ### Performance and resources
234
+
235
+ - **PR1 — Open-only observation.** Resize, mutation, captured resource-load,
236
+ window-resize, and visual-viewport-resize observation exists only while the
237
+ Popover component is open; cleanup disconnects listeners and observers and
238
+ cancels pending work.
239
+ - **PR2 — One measurement per frame.** Repeated signals while a measurement is
240
+ pending coalesce into one animation-frame callback.
241
+ - **PR3 — Stable state update.** Measurement updates overflow state only when the
242
+ overflow boolean changes.
243
+
244
+ ## Accessibility contract
245
+
246
+ - **AR1 — Trigger relationship.** The trigger exposes expanded state, the popup
247
+ relationship, and a role-appropriate popup type while mounted.
248
+ - **AR2 — Dialog naming.** Dialog mode requires a caller-provided accessible
249
+ label and places dialog/modal semantics on the painted surface. Missing naming
250
+ warns in development but does not synthesize a label.
251
+ - **AR3 — Focus containment.** Automatic entry and Tab/Shift+Tab behavior follow
252
+ the matrix above; a trapped surface with no tabbable descendant does not let
253
+ focus escape.
254
+ - **AR4 — Focus return.** Dismissal returns focus to the trigger when focus had
255
+ entered the closing Popover and would otherwise be lost.
256
+ - **AR5 — Evidence boundary.** Current automated tests establish DOM roles, ARIA
257
+ state, focus movement, and focus return. The Storybook manual-AT story is a
258
+ fixture, not a recorded result. PR #5373 records no named NVDA + Chrome or
259
+ VoiceOver + Safari announcement result, so this contract makes no AT
260
+ announcement claim.
261
+
262
+ ## Design relationships
263
+
264
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
265
+ | ---------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------ | -------------- | ------------------ |
266
+ | Trigger element | Supplies or references the control and anchor without becoming Popover-owned presentation. | Caller content | Supporting | FR6, AR1 |
267
+ | Popover surface | Paints the component surface, owns the canonical `popover` target, and carries fit, scroll, focus, and dialog behavior. | Current source and owner DEC-2 | Prominent | FR2–FR7, AR2–AR4 |
268
+ | Popover content | Renders caller-supplied interaction or information inside the surface. | Caller content | Prominent | FR2, FR6 |
269
+ | Fallback close control | Provides an end-of-trap close affordance without becoming the initial focus destination. | `component:Button` | Supporting | FR2, AR3 |
270
+
271
+ ### Theming anatomy
272
+
273
+ <!-- anatomy-theming:v1 -->
274
+
275
+ ```json
276
+ {
277
+ "Trigger element": {
278
+ "none": {
279
+ "reason": "intentional: The trigger is caller-owned and receives no Popover theming target."
280
+ }
281
+ },
282
+ "Popover surface": {"target": "popover"},
283
+ "Popover content": {
284
+ "none": {
285
+ "reason": "intentional: Caller-supplied content is caller-owned; normal CSS may inherit from the surface, but Popover provides no content target."
286
+ }
287
+ },
288
+ "Fallback close control": {
289
+ "delegatesTo": {"owner": "component:Button", "target": "button"}
290
+ }
291
+ }
292
+ ```
293
+
294
+ ### Deprecated compatibility target
295
+
296
+ `popover-surface` is a deprecated alias for `popover` on the same painted
297
+ surface. It is not anatomy and has no independent conceptual ownership. The
298
+ component doc marks it with `deprecatedFor: 'popover'`, so the anatomy validator
299
+ excludes it from the active target inventory while the runtime keeps emitting
300
+ it for existing themes.
301
+
302
+ Every public `usePopover` painted surface belongs to the broad `popover` target.
303
+ A composed component may add its own authoritative refinement target, such as
304
+ `selector-popup` or `multi-selector-popup`, on that same element. New direct
305
+ hook consumers that need distinct theme reachability provide and document an
306
+ owned `surfaceTarget`; they do not use `popover-surface`.
307
+
308
+ Automatic hook-wide `popover` emission and eventual removal of the compatibility
309
+ alias are runtime migration work outside this contract. Existing
310
+ `popover-surface` themes remain supported until that separately reviewed
311
+ migration includes target-inventory and regression-test updates plus changelog
312
+ or release guidance.
313
+
314
+ ## Family and system relationships
315
+
316
+ - `architecture:public-component-api` owns installable reachability and the
317
+ distinction between public package API and source-level implementation seams.
318
+ - `architecture:layer-runtime` owns the shared host, native popover lifecycle,
319
+ anchor geometry, portal/context behavior, and same-gesture dismissal guard;
320
+ Popover owns the component-specific fit, overflow, and focus composition above
321
+ that runtime.
322
+ - `architecture:interaction-modality` owns shared modality classification and
323
+ evidence expectations. Popover owns the destination matrix and derives the
324
+ internal focus choice from activation and role.
325
+ - `architecture:component-theming-surface` owns anatomy qualification and target
326
+ placement. `popover` is the one broad target on the painted surface;
327
+ `popover-surface` is only its deprecated compatibility alias. Caller content
328
+ adds no target, the fallback close control delegates to Button's target, and
329
+ composed components own any additional surface refinement target.
330
+ - `family:overlay-dismissal` owns topmost Escape and platform-close ordering.
331
+ Popover participates through the shared layer owner while retaining its local
332
+ focus, outside-dismiss, and open-state behavior.
333
+
334
+ ## Verification map
335
+
336
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
337
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
338
+ | Public boundary, FR1 | `Popover.test.tsx` compile-time public-surface assertions plus package/barrel inspection | Public component/hook imports and package-internal seam | Promoting internal controls or changing public operations fails type assertions or package review. | `audit:Popover/api` |
339
+ | FR2, AR2–AR4 | `Popover.test.tsx` focus/role suites and `useFocusTrap.test.tsx` container-entry suites | Pointer, keyboard/AT-style, read-only, neutral role, no autofocus, controlled, Tab/Shift+Tab, Escape, focus return | Changing a destination, selecting fallback close initially, or allowing focus escape fails focus assertions. | `audit:Popover/accessibility` |
340
+ | FR3, FR4 | `Popover.test.tsx` sizing/overflow suites; `Popover.stories.tsx` real-viewport scenarios for manual/browser evidence | Explicit width, trigger matching, all alignments, fitting and overflowing content | Removing a cap, reversing width precedence, or always enabling scroll fails emitted-style or overflow assertions. | `audit:Popover/layout` |
341
+ | FR5 | `Popover.test.tsx` scheduling and observer-lifecycle suites | Closed, opened, repeated signals, cleanup | Constructing observers while closed or measuring more than once per pending frame fails lifecycle assertions. | `audit:Popover/resources` |
342
+ | FR6, FR7 and theming anatomy | `Popover.test.tsx`, `Popover.doc.mjs`, `usePopover.doc.mjs`, `astryx theme targets Popover --json`, and `scripts/check-knowledge.mjs` | One real surface with canonical `popover`; deprecated alias on that element; composed-component refinements | A fake anatomy part, loss of compatibility output, missing deprecation metadata, or an active target without a real owner fails review or validation. | `audit:Popover/theming` |
343
+ | AR5 | `Popover.stories.tsx` manual-AT fixture and PR #5373 test record | Read-only dialog manual-AT fixture; no recorded NVDA/VoiceOver announcement result | A fixture without recorded AT/browser observations cannot be cited as announcement proof. | `audit:Popover/at-evidence` |
344
+
345
+ ## Decision log
346
+
347
+ ### DEC-1 — One canonical visibility operation model
348
+
349
+ **Reference:** `component:Popover/DEC-1`
350
+
351
+ **Decider:** Cindy Zhang, 2026-08-31
352
+
353
+ Showing, hiding, and toggling are one visibility lifecycle. Options may refine the
354
+ opening half of toggle, but a package-internal need for a derived focus destination
355
+ does not establish a durable parallel toggle API. Popover derives focus placement
356
+ from activation, role, content, and autofocus policy; consumers are not asked to
357
+ choose it.
358
+
359
+ Rejected: preserving a separate `toggleWithOptions` concept or exposing
360
+ `focusTarget` as durable API. Both describe implementation choices within the
361
+ same caller operation, and public focus selection would let callers create
362
+ inconsistent or inaccessible destinations.
363
+
364
+ ### DEC-2 — One canonical Popover surface target
365
+
366
+ **Reference:** `component:Popover/DEC-2`
367
+
368
+ **Decider:** Cindy Zhang, 2026-08-31
369
+
370
+ `popover` is the broad canonical theming baseline automatically owned by every
371
+ painted surface created by `<Popover>` or public `usePopover`.
372
+ `popover-surface` is deprecated compatibility output on that same element, not a
373
+ second anatomy part or equal owner. Existing themes using it remain supported
374
+ through a documented migration window.
375
+
376
+ Composed components keep authoritative refinement targets such as
377
+ `selector-popup` and `multi-selector-popup`. Optional `surfaceTarget` adds that
378
+ owned refinement on the same surface; it does not replace the broad `popover`
379
+ baseline. New direct hook consumers that need distinct reachability provide and
380
+ document an owned target rather than depending on `popover-surface`.
381
+
382
+ Rejected: treating `popover` and `popover-surface` as two durable sibling targets,
383
+ or inventing a “Shared hook surface” anatomy part to satisfy inventory coverage.
384
+ Both make one painted element look like two design concepts and preserve an
385
+ accidental implementation name as permanent public structure.
386
+
387
+ ## Verification gaps
388
+
389
+ These implementation and evidence items remain required follow-up, but they do
390
+ not block acceptance of the semantic contract above.
391
+
392
+ - **VG1 — Internal operation naming.** Current source still names a
393
+ package-internal wider toggle helper separately. This contract treats it as an
394
+ implementation seam to reconcile in future runtime work, not as public or
395
+ durable package API. This documentation-only PR does not rename it.
396
+ - **VG2 — Real browser behavior.** Unit tests assert emitted sizing styles and
397
+ synthetic dimensions, not rendered viewport layout. Native popover light
398
+ dismiss, top-layer ordering, anchor geometry, and rendered focus behavior still
399
+ require real Chromium/WebKit evidence when changed.
400
+ - **VG3 — AT announcement.** The current story provides manual instructions, but
401
+ named NVDA + Chrome and VoiceOver + Safari results are absent. No announcement
402
+ outcome is claimed.
403
+ - **VG4 — Target migration.** Current runtime still emits `popover-surface` as
404
+ the automatic shared class and reaches `popover` through Popover's explicit
405
+ `surfaceTarget`. A separate implementation must make `popover` automatic for
406
+ every public hook surface while preserving the alias, then verify direct-hook
407
+ and composed-component target inventories before any later removal.
408
+
409
+ ## Open questions
410
+
411
+ None. DEC-1 settles the visibility model and derived focus destination; DEC-2
412
+ settles canonical target ownership and compatibility direction. The remaining
413
+ items are verification or separately reviewed implementation work, not human API
414
+ questions.
415
+
416
+ ## Content boundary
417
+
418
+ This file does not duplicate consumer signatures, prop tables, examples,
419
+ implementation steps, shared layer algorithms, or family dismissal rules. It
420
+ links to their owners and records only Popover-specific semantics, boundaries,
421
+ and invariants.