@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.
- package/dist/AppShell/AppShell.d.ts +2 -2
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +10 -7
- package/dist/Banner/Banner.d.ts +5 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +7 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +2 -2
- package/dist/Chat/ChatComposer.d.ts +2 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +21 -2
- package/dist/Chat/ChatToolCalls.d.ts +1 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -34
- package/dist/Chat/useChatNewMessages.js +3 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +47 -13
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +269 -162
- package/dist/DateTimeInput/NativeDateSegment.d.ts +24 -0
- package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeDateSegment.js +235 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts +30 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeTimeSegment.js +248 -0
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +95 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.js +103 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +2 -4
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +10 -4
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +3 -5
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +2 -4
- package/dist/Layout/Layout.d.ts +7 -8
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +7 -8
- package/dist/MultiSelector/MultiSelector.d.ts +11 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +89 -45
- package/dist/RadioList/RadioListItem.d.ts +30 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +17 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +102 -44
- package/dist/Resizable/index.d.ts +2 -0
- package/dist/Resizable/index.d.ts.map +1 -1
- package/dist/Resizable/index.js +1 -0
- package/dist/Resizable/useResizable.d.ts +89 -8
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +521 -38
- package/dist/Resizable/utils.d.ts +35 -0
- package/dist/Resizable/utils.d.ts.map +1 -0
- package/dist/Resizable/utils.js +27 -0
- package/dist/Selector/Selector.d.ts +10 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +105 -57
- package/dist/Selector/useSelectorPresentation.d.ts +1 -0
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +17 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -5
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +9 -10
- package/dist/Stepper/Step.d.ts +2 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +75 -11
- package/dist/Stepper/Stepper.d.ts.map +1 -1
- package/dist/Stepper/Stepper.js +1 -0
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -3
- package/dist/Table/index.d.ts +16 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +4 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +8 -9
- package/dist/Table/plugins/rowStatus/index.d.ts +1 -1
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +11 -30
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +108 -62
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +9 -1
- package/dist/Text/useTruncation.d.ts +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +8 -7
- package/dist/TimeInput/TimeInput.d.ts +16 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +98 -60
- package/dist/TimeInput/index.d.ts +1 -1
- package/dist/TimeInput/index.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.d.ts +2 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +4 -145
- package/dist/Timestamp/formatRelativeTime.d.ts +20 -0
- package/dist/Timestamp/formatRelativeTime.d.ts.map +1 -0
- package/dist/Timestamp/formatRelativeTime.js +81 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +125 -77
- package/dist/Tokenizer/Tokenizer.d.ts +0 -38
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +94 -26
- package/dist/Tokenizer/useEndLaneReserve.d.ts +31 -0
- package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
- package/dist/Tokenizer/useEndLaneReserve.js +136 -0
- package/dist/Tooltip/useTooltip.d.ts +1 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +53 -42
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +85 -30
- package/dist/Typeahead/Typeahead.d.ts +0 -21
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +108 -67
- package/dist/Typeahead/busyIndicatorLane.d.ts +62 -0
- package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
- package/dist/Typeahead/busyIndicatorLane.js +98 -0
- package/dist/astryx.css +25 -7
- package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
- package/dist/hooks/useFocusReturnVisibility.js +3 -5
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +11 -11
- package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
- package/dist/hooks/useScrollOverflow.js +7 -4
- package/dist/theme/defineTheme.d.ts +13 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/localTokens.d.ts +18 -0
- package/dist/theme/localTokens.d.ts.map +1 -0
- package/dist/theme/localTokens.js +162 -0
- package/dist/utils/interactionModality.d.ts +6 -28
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +72 -37
- package/dist/utils/sharedResizeObserver.d.ts +17 -9
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +54 -12
- package/locales/en.json +8 -0
- package/locales/pseudo.json +6 -0
- package/package.json +7 -2
- package/src/AlertDialog/useImperativeAlertDialog.test.tsx +163 -0
- package/src/AppShell/AppShell.doc.mjs +4 -3
- package/src/AppShell/AppShell.test.tsx +21 -0
- package/src/AppShell/AppShell.tsx +12 -7
- package/src/Banner/Banner.doc.mjs +5 -1
- package/src/Banner/Banner.tsx +12 -1
- package/src/BottomSheet/BottomSheet.doc.mjs +31 -0
- package/src/BottomSheet/BottomSheet.spec.md +178 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
- package/src/Button/Button.doc.mjs +56 -0
- package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
- package/src/Calendar/hooks/useCalendarConstraints.test.ts +153 -0
- package/src/Calendar/hooks/useCalendarDays.test.ts +265 -0
- package/src/Calendar/hooks/useCalendarNavigation.test.ts +252 -0
- package/src/Carousel/Carousel.test.tsx +83 -0
- package/src/Carousel/Carousel.tsx +8 -2
- package/src/Chat/ChatComposer.doc.mjs +7 -4
- package/src/Chat/ChatComposer.test.tsx +84 -2
- package/src/Chat/ChatComposer.tsx +45 -3
- package/src/Chat/ChatSendButton.test.tsx +189 -0
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/ChatToolCalls.test.tsx +33 -1
- package/src/Chat/ChatToolCalls.tsx +13 -34
- package/src/Chat/useChatNewMessages.ts +3 -3
- package/src/Chat/useChatPasteAsToken.test.ts +191 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
- package/src/CheckboxList/CheckboxList.spec.md +215 -0
- package/src/CheckboxList/CheckboxList.test.tsx +45 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
- package/src/CheckboxList/CheckboxListItem.tsx +5 -3
- package/src/Collapsible/useCollapsible.test.tsx +236 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
- package/src/CommandPalette/CommandPalette.spec.md +224 -0
- package/src/CommandPalette/CommandPaletteEmpty.test.tsx +101 -0
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.spec.md +190 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +48 -0
- package/src/ContextMenu/ContextMenu.spec.md +207 -0
- package/src/DateTimeInput/DateTimeInput.doc.mjs +43 -23
- package/src/DateTimeInput/DateTimeInput.tsx +388 -181
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +10 -2
- package/src/DateTimeInput/NativeDateSegment.tsx +308 -0
- package/src/DateTimeInput/NativePickerSegments.test.tsx +626 -0
- package/src/DateTimeInput/NativeTimeSegment.tsx +331 -0
- package/src/DateTimeInput/index.ts +1 -0
- package/src/DateTimeInput/nativePickerSegmentStyles.ts +120 -0
- package/src/Divider/Divider.doc.mjs +24 -0
- package/src/Divider/Divider.spec.md +157 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +104 -0
- package/src/DropdownMenu/DropdownMenu.spec.md +246 -0
- package/src/DropdownMenu/DropdownMenu.tsx +2 -4
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/Field.test.tsx +39 -0
- package/src/Field/Field.tsx +18 -1
- package/src/Field/InputClearButton.test.tsx +68 -6
- package/src/Field/PanelSearchInput.tsx +3 -5
- package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
- package/src/FieldStatus/FieldStatus.spec.md +213 -0
- package/src/FieldStatus/FieldStatus.test.tsx +17 -0
- package/src/FieldStatus/FieldStatus.tsx +7 -2
- package/src/Grid/Grid.doc.mjs +19 -0
- package/src/Grid/Grid.spec.md +162 -0
- package/src/Icon/Icon.doc.mjs +196 -48
- package/src/Icon/Icon.spec.md +192 -0
- package/src/IconButton/IconButton.doc.mjs +38 -0
- package/src/Kbd/Kbd.doc.mjs +18 -0
- package/src/Kbd/Kbd.spec.md +142 -0
- package/src/Layer/useTouchTrigger.ts +2 -4
- package/src/Layout/Layout.doc.mjs +57 -17
- package/src/Layout/Layout.spec.md +235 -0
- package/src/Layout/Layout.test.tsx +1 -1
- package/src/Layout/Layout.tsx +7 -8
- package/src/Layout/LayoutHeader.doc.mjs +9 -0
- package/src/Layout/LayoutPanel.doc.mjs +4 -3
- package/src/Lightbox/Lightbox.doc.mjs +149 -33
- package/src/Lightbox/Lightbox.spec.md +198 -0
- package/src/Lightbox/useLightbox.test.tsx +263 -0
- package/src/Markdown/Markdown.doc.mjs +60 -0
- package/src/Markdown/Markdown.spec.md +207 -0
- package/src/MobileNav/MobileNav.doc.mjs +140 -32
- package/src/MobileNav/MobileNav.spec.md +209 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +42 -0
- package/src/MoreMenu/MoreMenu.spec.md +222 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +124 -1
- package/src/MultiSelector/MultiSelector.spec.md +293 -0
- package/src/MultiSelector/MultiSelector.test.tsx +305 -2
- package/src/MultiSelector/MultiSelector.tsx +124 -55
- package/src/NavIcon/NavIcon.doc.mjs +17 -0
- package/src/NavIcon/NavIcon.spec.md +134 -0
- package/src/NavMenu/NavHeadingMenu.spec.md +210 -0
- package/src/NavMenu/NavMenu.doc.mjs +37 -0
- package/src/Outline/Outline.doc.mjs +35 -0
- package/src/Outline/Outline.spec.md +162 -0
- package/src/OverflowList/OverflowList.doc.mjs +24 -0
- package/src/OverflowList/OverflowList.spec.md +157 -0
- package/src/Pagination/Pagination.doc.mjs +74 -0
- package/src/Pagination/Pagination.spec.md +226 -0
- package/src/Popover/Popover.doc.mjs +264 -65
- package/src/Popover/Popover.spec.md +421 -0
- package/src/Popover/usePopover.doc.mjs +208 -33
- package/src/PowerSearch/PowerSearch.spec.md +291 -0
- package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +253 -0
- package/src/PowerSearch/PowerSearchToken.test.tsx +228 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
- package/src/ProgressBar/ProgressBar.spec.md +261 -0
- package/src/RadioList/RadioList.test.tsx +136 -2
- package/src/RadioList/RadioListItem.doc.mjs +30 -11
- package/src/RadioList/RadioListItem.tsx +44 -8
- package/src/Resizable/Resizable.doc.mjs +130 -24
- package/src/Resizable/Resizable.spec.md +246 -0
- package/src/Resizable/ResizeHandle.test.tsx +177 -56
- package/src/Resizable/ResizeHandle.tsx +128 -45
- package/src/Resizable/index.ts +2 -0
- package/src/Resizable/shippedDirections.test.ts +462 -0
- package/src/Resizable/useResizable.doc.mjs +124 -29
- package/src/Resizable/useResizable.test.ts +1277 -3
- package/src/Resizable/useResizable.ts +760 -48
- package/src/Resizable/utils.test.ts +74 -0
- package/src/Resizable/utils.ts +35 -0
- package/src/Section/Section.doc.mjs +17 -0
- package/src/Section/Section.spec.md +139 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
- package/src/SegmentedControl/SegmentedControl.spec.md +152 -0
- package/src/Selector/Selector.doc.mjs +133 -97
- package/src/Selector/Selector.spec.md +300 -0
- package/src/Selector/Selector.test.tsx +318 -1
- package/src/Selector/Selector.tsx +127 -60
- package/src/Selector/useSelectorPresentation.ts +24 -4
- package/src/SideNav/SideNav.test.tsx +3 -3
- package/src/SideNav/SideNavCollapseButton.doc.mjs +8 -0
- package/src/SideNav/SideNavItem.doc.mjs +1 -1
- package/src/Skeleton/Skeleton.doc.mjs +12 -0
- package/src/Skeleton/Skeleton.spec.md +127 -0
- package/src/Slider/Slider.doc.mjs +184 -30
- package/src/Slider/Slider.spec.md +224 -0
- package/src/Slider/Slider.tsx +2 -5
- package/src/Spinner/Spinner.doc.mjs +5 -5
- package/src/Spinner/Spinner.test.tsx +32 -7
- package/src/Spinner/Spinner.tsx +46 -14
- package/src/Stack/Stack.doc.mjs +22 -0
- package/src/Stack/Stack.spec.md +155 -0
- package/src/StatusDot/StatusDot.doc.mjs +17 -0
- package/src/StatusDot/StatusDot.spec.md +138 -0
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +118 -5
- package/src/Stepper/Stepper.doc.mjs +51 -1
- package/src/Stepper/Stepper.spec.md +245 -0
- package/src/Stepper/Stepper.test.tsx +315 -0
- package/src/Stepper/Stepper.tsx +8 -0
- package/src/Switch/Switch.doc.mjs +40 -0
- package/src/Switch/Switch.spec.md +175 -0
- package/src/TabList/TabList.tsx +2 -3
- package/src/Table/Table.doc.mjs +102 -24
- package/src/Table/Table.perf.test.tsx +51 -1
- package/src/Table/Table.spec.md +325 -0
- package/src/Table/TableHeaderCell.test.tsx +291 -0
- package/src/Table/index.ts +19 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -12
- package/src/Table/plugins/filtering/useTableFilterState.test.tsx +143 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +2 -1
- package/src/Table/plugins/rowStatus/index.ts +1 -4
- package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +92 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +431 -56
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +155 -84
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +72 -0
- package/src/Table/plugins/sortable/useTableSortable.tsx +18 -1
- package/src/Table/useTableGroupedRows.doc.mjs +2 -2
- package/src/Table/useTableRowStatus.doc.mjs +5 -5
- package/src/Text/Text.doc.mjs +190 -43
- package/src/Text/Text.spec.md +206 -0
- package/src/Text/useTruncation.ts +8 -7
- package/src/TextArea/TextArea.doc.mjs +255 -45
- package/src/TextArea/TextArea.spec.md +205 -0
- package/src/TimeInput/NativeTimeInput.test.tsx +269 -0
- package/src/TimeInput/TimeInput.doc.mjs +47 -23
- package/src/TimeInput/TimeInput.tsx +109 -50
- package/src/TimeInput/index.ts +1 -0
- package/src/Timestamp/Timestamp.doc.mjs +2 -2
- package/src/Timestamp/Timestamp.test.tsx +75 -3
- package/src/Timestamp/Timestamp.tsx +7 -153
- package/src/Timestamp/formatRelativeTime.ts +96 -0
- package/src/Toast/ToastViewport.test.tsx +194 -0
- package/src/Toast/ToastViewport.tsx +136 -58
- package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
- package/src/Tokenizer/Tokenizer.spec.md +293 -0
- package/src/Tokenizer/Tokenizer.test.tsx +335 -1
- package/src/Tokenizer/Tokenizer.tsx +129 -46
- package/src/Tokenizer/useEndLaneReserve.ts +146 -0
- package/src/Toolbar/Toolbar.doc.mjs +19 -0
- package/src/Toolbar/Toolbar.spec.md +174 -0
- package/src/Tooltip/Tooltip.doc.mjs +17 -0
- package/src/Tooltip/Tooltip.spec.md +142 -0
- package/src/Tooltip/Tooltip.test.tsx +21 -1
- package/src/Tooltip/useTooltip.test.tsx +318 -0
- package/src/Tooltip/useTooltip.tsx +60 -39
- package/src/TreeList/TreeList.doc.mjs +58 -0
- package/src/TreeList/TreeList.spec.md +224 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -25
- package/src/Typeahead/Typeahead.doc.mjs +89 -1
- package/src/Typeahead/Typeahead.spec.md +257 -0
- package/src/Typeahead/Typeahead.test.tsx +502 -1
- package/src/Typeahead/Typeahead.tsx +187 -69
- package/src/Typeahead/TypeaheadItem.test.tsx +93 -2
- package/src/Typeahead/busyIndicatorLane.tsx +109 -0
- package/src/__tests__/stylexDeclarations.ts +51 -0
- package/src/hooks/useFocusReturnVisibility.ts +3 -5
- package/src/hooks/useOverflow.ts +11 -11
- package/src/hooks/useScrollLock.test.ts +103 -0
- package/src/hooks/useScrollOverflow.ts +7 -4
- package/src/i18n/useTranslator.test.tsx +197 -0
- package/src/theme/defineTheme.test.ts +227 -0
- package/src/theme/defineTheme.ts +30 -0
- package/src/theme/derivedVarRegistry.test.ts +6 -0
- package/src/theme/generateThemeRules.ts +4 -1
- package/src/theme/localTokens.ts +272 -0
- package/src/theme/themingTargets.test.ts +126 -28
- package/src/utils/interactionModality.test.ts +83 -0
- package/src/utils/interactionModality.ts +88 -36
- package/src/utils/sharedResizeObserver.test.ts +124 -5
- 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.
|