@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d
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/CHANGELOG.md +165 -0
- package/README.md +12 -12
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +2 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +0 -1
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +0 -1
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts +8 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +0 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +9 -5
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +51 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +167 -99
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +32 -6
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +16 -6
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +3 -3
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +33 -1
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -9
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +16 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +18 -7
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +27 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +141 -42
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +15 -1
- package/dist/Popover/Popover.d.ts +18 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -2
- package/dist/Popover/usePopover.d.ts +38 -3
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +24 -9
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +24 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +122 -43
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +2 -0
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +36 -9
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +87 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +11 -8
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +10 -1
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +66 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +147 -76
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +131 -3
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +26 -4
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +56 -9
- package/dist/TopNav/TopNavHeading.d.ts +7 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +8 -0
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +69 -6
- package/dist/Typeahead/Typeahead.d.ts +26 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +65 -29
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +18 -0
- package/dist/astryx.umd.js +55 -55
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/docs.mjs +2 -2
- package/package.json +12 -8
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.tsx +3 -16
- package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
- package/src/ButtonGroup/ButtonGroup.tsx +0 -1
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposerInput.test.tsx +26 -7
- package/src/Chat/ChatComposerInput.tsx +0 -1
- package/src/Chat/ChatDictationButton.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +22 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +192 -26
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/CheckboxList/CheckboxListItem.tsx +0 -3
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +121 -0
- package/src/Citation/Citation.tsx +15 -3
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +63 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +286 -56
- package/src/DateInput/DateInput.test.tsx +248 -2
- package/src/DateInput/DateInput.tsx +196 -100
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/Field/Field.doc.mjs +59 -18
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +17 -4
- package/src/Grid/Grid.test.tsx +43 -30
- package/src/Grid/Grid.tsx +38 -3
- package/src/Icon/Icon.doc.mjs +3 -3
- package/src/InputGroup/InputGroup.doc.mjs +111 -23
- package/src/InputGroup/InputGroup.test.tsx +257 -60
- package/src/InputGroup/InputGroup.tsx +23 -5
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/groupStyles.ts +7 -1
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +35 -3
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +5 -0
- package/src/Layer/useLayer.test.tsx +111 -0
- package/src/Layer/useLayer.tsx +90 -9
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -0
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +50 -0
- package/src/Link/Link.tsx +39 -4
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +7 -0
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +194 -48
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +117 -5
- package/src/Pagination/Pagination.tsx +21 -1
- package/src/Popover/Popover.doc.mjs +26 -0
- package/src/Popover/Popover.test.tsx +121 -0
- package/src/Popover/Popover.tsx +23 -2
- package/src/Popover/usePopover.doc.mjs +9 -3
- package/src/Popover/usePopover.tsx +70 -12
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +34 -26
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +26 -0
- package/src/Selector/Selector.test.tsx +387 -15
- package/src/Selector/Selector.tsx +175 -67
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +48 -0
- package/src/SideNav/SideNavHeading.tsx +8 -2
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +15 -0
- package/src/Slider/Slider.test.tsx +155 -2
- package/src/Slider/Slider.tsx +53 -5
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +6 -0
- package/src/TabList/TabList.test.tsx +251 -0
- package/src/TabList/TabList.tsx +103 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +21 -17
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +10 -0
- package/src/Table/Table.tsx +8 -0
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +3 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- package/src/Table/useTableStickyColumns.doc.mjs +2 -2
- package/src/Text/Text.doc.mjs +18 -18
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
- package/src/TimeInput/TimeInput.doc.mjs +340 -60
- package/src/TimeInput/TimeInput.test.tsx +255 -7
- package/src/TimeInput/TimeInput.tsx +176 -70
- package/src/Timestamp/Timestamp.doc.mjs +19 -19
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +214 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +37 -1
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +68 -0
- package/src/Tooltip/useTooltip.tsx +55 -8
- package/src/TopNav/TopNav.test.tsx +50 -0
- package/src/TopNav/TopNavHeading.tsx +17 -1
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +93 -9
- package/src/Typeahead/Typeahead.doc.mjs +141 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +105 -33
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/docs-script.test.mjs +50 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +10 -5
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -9,10 +9,26 @@
|
|
|
9
9
|
* SYNC: When Pagination.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {
|
|
12
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
|
+
import {
|
|
14
|
+
render,
|
|
15
|
+
screen,
|
|
16
|
+
within,
|
|
17
|
+
fireEvent,
|
|
18
|
+
act,
|
|
19
|
+
waitFor,
|
|
20
|
+
} from '@testing-library/react';
|
|
14
21
|
import userEvent from '@testing-library/user-event';
|
|
15
22
|
import {Pagination, generatePageRange} from './Pagination';
|
|
23
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
__resetLiveRegionsForTest();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function politeRegion(): HTMLElement | null {
|
|
30
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
31
|
+
}
|
|
16
32
|
|
|
17
33
|
// =============================================================================
|
|
18
34
|
// generatePageRange helper
|
|
@@ -239,6 +255,65 @@ describe('Pagination', () => {
|
|
|
239
255
|
});
|
|
240
256
|
});
|
|
241
257
|
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// pageSize guarding
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
|
|
262
|
+
describe('pageSize guarding', () => {
|
|
263
|
+
it('does not crash the dots variant when pageSize is 0', () => {
|
|
264
|
+
render(
|
|
265
|
+
<Pagination
|
|
266
|
+
page={1}
|
|
267
|
+
onChange={() => {}}
|
|
268
|
+
totalItems={5}
|
|
269
|
+
pageSize={0}
|
|
270
|
+
variant="dots"
|
|
271
|
+
/>,
|
|
272
|
+
);
|
|
273
|
+
const group = screen.getByRole('group', {name: 'Page indicators'});
|
|
274
|
+
expect(within(group).getAllByRole('button')).toHaveLength(5);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('treats NaN pageSize as the default', () => {
|
|
278
|
+
render(
|
|
279
|
+
<Pagination
|
|
280
|
+
page={1}
|
|
281
|
+
onChange={() => {}}
|
|
282
|
+
totalItems={50}
|
|
283
|
+
pageSize={NaN}
|
|
284
|
+
variant="compact"
|
|
285
|
+
/>,
|
|
286
|
+
);
|
|
287
|
+
expect(screen.getByText('Page 1 of 5')).toBeInTheDocument();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('clamps negative pageSize to 1', () => {
|
|
291
|
+
render(
|
|
292
|
+
<Pagination
|
|
293
|
+
page={1}
|
|
294
|
+
onChange={() => {}}
|
|
295
|
+
totalItems={5}
|
|
296
|
+
pageSize={-10}
|
|
297
|
+
variant="compact"
|
|
298
|
+
/>,
|
|
299
|
+
);
|
|
300
|
+
expect(screen.getByText('Page 1 of 5')).toBeInTheDocument();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('floors fractional pageSize', () => {
|
|
304
|
+
render(
|
|
305
|
+
<Pagination
|
|
306
|
+
page={1}
|
|
307
|
+
onChange={() => {}}
|
|
308
|
+
totalItems={50}
|
|
309
|
+
pageSize={2.5}
|
|
310
|
+
variant="compact"
|
|
311
|
+
/>,
|
|
312
|
+
);
|
|
313
|
+
expect(screen.getByText('Page 1 of 25')).toBeInTheDocument();
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
242
317
|
// ---------------------------------------------------------------------------
|
|
243
318
|
// Variant: dots
|
|
244
319
|
// ---------------------------------------------------------------------------
|
|
@@ -304,6 +379,38 @@ describe('Pagination', () => {
|
|
|
304
379
|
// ---------------------------------------------------------------------------
|
|
305
380
|
|
|
306
381
|
describe('page change callbacks', () => {
|
|
382
|
+
it('does not announce on initial mount', () => {
|
|
383
|
+
render(<Pagination page={1} onChange={() => {}} totalPages={10} />);
|
|
384
|
+
expect(politeRegion()).toBeNull();
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('announces the new page politely when navigating', async () => {
|
|
388
|
+
const user = userEvent.setup();
|
|
389
|
+
render(<Pagination page={2} onChange={() => {}} totalPages={10} />);
|
|
390
|
+
await user.click(screen.getByRole('button', {name: 'Go to page 3'}));
|
|
391
|
+
await waitFor(() => {
|
|
392
|
+
expect(politeRegion()).toHaveTextContent('Page 3 of 10');
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('announces the next page when clicking next', async () => {
|
|
397
|
+
const user = userEvent.setup();
|
|
398
|
+
render(<Pagination page={2} onChange={() => {}} totalPages={5} />);
|
|
399
|
+
await user.click(screen.getByRole('button', {name: 'Go to next page'}));
|
|
400
|
+
await waitFor(() => {
|
|
401
|
+
expect(politeRegion()).toHaveTextContent('Page 3 of 5');
|
|
402
|
+
});
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('announces without a total when only hasMore is known', async () => {
|
|
406
|
+
const user = userEvent.setup();
|
|
407
|
+
render(<Pagination page={1} onChange={() => {}} hasMore />);
|
|
408
|
+
await user.click(screen.getByRole('button', {name: 'Go to next page'}));
|
|
409
|
+
await waitFor(() => {
|
|
410
|
+
expect(politeRegion()).toHaveTextContent('Page 2');
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
307
414
|
it('calls onChange when clicking a page button', async () => {
|
|
308
415
|
const user = userEvent.setup();
|
|
309
416
|
const onChange = vi.fn();
|
|
@@ -395,7 +502,9 @@ describe('Pagination', () => {
|
|
|
395
502
|
// reflects the page being navigated to.
|
|
396
503
|
await user.click(screen.getByRole('button', {name: 'Go to next page'}));
|
|
397
504
|
expect(changeAction).toHaveBeenCalledWith(2);
|
|
398
|
-
expect(
|
|
505
|
+
expect(
|
|
506
|
+
within(screen.getByRole('navigation')).getByText('Page 2 of 5'),
|
|
507
|
+
).toBeInTheDocument();
|
|
399
508
|
|
|
400
509
|
await act(async () => {
|
|
401
510
|
resolveAction?.();
|
|
@@ -425,14 +534,17 @@ describe('Pagination', () => {
|
|
|
425
534
|
);
|
|
426
535
|
|
|
427
536
|
const next = screen.getByRole('button', {name: 'Go to next page'});
|
|
537
|
+
const nav = screen.getByRole('navigation');
|
|
428
538
|
await act(async () => {
|
|
429
539
|
fireEvent.click(next);
|
|
430
540
|
});
|
|
431
|
-
|
|
541
|
+
// Scope to the nav landmark: the live region on document.body also
|
|
542
|
+
// carries the announced page text.
|
|
543
|
+
expect(within(nav).getByText('Page 2 of 5')).toBeInTheDocument();
|
|
432
544
|
await act(async () => {
|
|
433
545
|
fireEvent.click(next);
|
|
434
546
|
});
|
|
435
|
-
expect(
|
|
547
|
+
expect(within(nav).getByText('Page 3 of 5')).toBeInTheDocument();
|
|
436
548
|
|
|
437
549
|
expect(changeAction).toHaveBeenCalledTimes(2);
|
|
438
550
|
expect(changeAction).toHaveBeenNthCalledWith(1, 2);
|
|
@@ -34,6 +34,7 @@ import {Button} from '../Button';
|
|
|
34
34
|
import {Icon} from '../Icon';
|
|
35
35
|
import {Selector} from '../Selector';
|
|
36
36
|
import {Text} from '../Text';
|
|
37
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
37
38
|
import {mergeProps} from '../utils';
|
|
38
39
|
import type {BaseProps} from '../BaseProps';
|
|
39
40
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -335,7 +336,7 @@ export function Pagination({
|
|
|
335
336
|
totalItems,
|
|
336
337
|
totalPages: totalPagesProp,
|
|
337
338
|
hasMore,
|
|
338
|
-
pageSize = 10,
|
|
339
|
+
pageSize: pageSizeProp = 10,
|
|
339
340
|
pageSizeOptions,
|
|
340
341
|
onPageSizeChange,
|
|
341
342
|
variant = 'pages',
|
|
@@ -351,6 +352,20 @@ export function Pagination({
|
|
|
351
352
|
}: PaginationProps) {
|
|
352
353
|
const [, startTransition] = useTransition();
|
|
353
354
|
|
|
355
|
+
// pageSize is typed as number, so 0, NaN, and negatives are valid at the
|
|
356
|
+
// type level but yield Infinity/NaN page counts, and
|
|
357
|
+
// Array.from({length: Infinity}) crashes the dots variant. Coerce to a
|
|
358
|
+
// positive integer; non-finite values fall back to the default.
|
|
359
|
+
const pageSize = Number.isFinite(pageSizeProp)
|
|
360
|
+
? Math.max(1, Math.floor(pageSizeProp))
|
|
361
|
+
: 10;
|
|
362
|
+
|
|
363
|
+
// Announce page changes politely (navigation-10). The controls carry no
|
|
364
|
+
// live region, so page transitions were previously silent to screen readers.
|
|
365
|
+
// Only user-driven changes go through handlePageChange, so initial mount is
|
|
366
|
+
// never announced.
|
|
367
|
+
const announce = useAnnounce();
|
|
368
|
+
|
|
354
369
|
// Track the page optimistically so rapid prev/next clicks advance from the
|
|
355
370
|
// in-flight target instead of stalling on the last committed page.
|
|
356
371
|
const [optimisticPage, setOptimisticPage] = useOptimistic(page);
|
|
@@ -384,6 +399,11 @@ export function Pagination({
|
|
|
384
399
|
// Keep onChange urgent so controlled page state updates in the same commit
|
|
385
400
|
// as the click; only the optimistic indicator and changeAction defer.
|
|
386
401
|
onChange(newPage);
|
|
402
|
+
announce(
|
|
403
|
+
computedTotalPages != null
|
|
404
|
+
? `Page ${newPage} of ${computedTotalPages}`
|
|
405
|
+
: `Page ${newPage}`,
|
|
406
|
+
);
|
|
387
407
|
startTransition(async () => {
|
|
388
408
|
setOptimisticPage(newPage);
|
|
389
409
|
await changeAction?.(newPage);
|
|
@@ -90,6 +90,18 @@ export const docs = {
|
|
|
90
90
|
description: 'Whether to auto-focus the first focusable element when the popover opens. Set to false for inline showcases or documentation previews.',
|
|
91
91
|
default: 'true',
|
|
92
92
|
},
|
|
93
|
+
{
|
|
94
|
+
name: 'hasLightDismiss',
|
|
95
|
+
type: 'boolean',
|
|
96
|
+
description: 'Whether clicking outside dismisses the popover. Set to false for surfaces that stay open until explicitly dismissed, like onboarding coachmarks.',
|
|
97
|
+
default: 'true',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'hasEscapeDismiss',
|
|
101
|
+
type: 'boolean',
|
|
102
|
+
description: 'Whether pressing Escape dismisses the popover. Only takes full effect together with hasLightDismiss={false}, since native light dismiss also closes on Escape.',
|
|
103
|
+
default: 'true',
|
|
104
|
+
},
|
|
93
105
|
{
|
|
94
106
|
name: 'xstyle',
|
|
95
107
|
type: 'StyleXStyles',
|
|
@@ -219,6 +231,18 @@ export const docsZh = {
|
|
|
219
231
|
description: '弹出框打开时是否自动聚焦第一个可聚焦元素。内联展示或文档预览设为 false。',
|
|
220
232
|
default: 'true',
|
|
221
233
|
},
|
|
234
|
+
{
|
|
235
|
+
name: 'hasLightDismiss',
|
|
236
|
+
type: 'boolean',
|
|
237
|
+
description: '点击外部是否关闭弹出框。需要显式关闭的界面(如新手引导提示)设为 false。',
|
|
238
|
+
default: 'true',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: 'hasEscapeDismiss',
|
|
242
|
+
type: 'boolean',
|
|
243
|
+
description: '按 Escape 是否关闭弹出框。仅在 hasLightDismiss={false} 时生效,因为原生 light dismiss 行为同样响应 Escape。',
|
|
244
|
+
default: 'true',
|
|
245
|
+
},
|
|
222
246
|
],
|
|
223
247
|
},
|
|
224
248
|
],
|
|
@@ -291,6 +315,8 @@ export const docsDense = {
|
|
|
291
315
|
hasCloseButton: 'Whether to include hidden close button for accessibility.',
|
|
292
316
|
closeButtonLabel: 'Label for hidden close button.',
|
|
293
317
|
hasAutoFocus: 'Auto-focus first element on open; false for showcases.',
|
|
318
|
+
hasLightDismiss: 'Outside click dismisses; false for explicit-dismiss surfaces (coachmarks).',
|
|
319
|
+
hasEscapeDismiss: 'Escape dismisses; full effect only with hasLightDismiss=false.',
|
|
294
320
|
},
|
|
295
321
|
},
|
|
296
322
|
],
|
|
@@ -13,6 +13,7 @@ import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
|
|
|
13
13
|
import {render, screen, fireEvent} from '@testing-library/react';
|
|
14
14
|
import React, {useRef} from 'react';
|
|
15
15
|
import {Popover} from './Popover';
|
|
16
|
+
import {Dialog} from '../Dialog';
|
|
16
17
|
|
|
17
18
|
// Store original matches to restore later
|
|
18
19
|
const originalMatches = HTMLElement.prototype.matches;
|
|
@@ -233,4 +234,124 @@ describe('Popover', () => {
|
|
|
233
234
|
);
|
|
234
235
|
warnSpy.mockRestore();
|
|
235
236
|
});
|
|
237
|
+
|
|
238
|
+
describe('dismiss controls', () => {
|
|
239
|
+
// jsdom does not implement <dialog> showModal/close, needed by the
|
|
240
|
+
// host-Dialog fall-through test below.
|
|
241
|
+
beforeAll(() => {
|
|
242
|
+
HTMLDialogElement.prototype.showModal = vi.fn(function (
|
|
243
|
+
this: HTMLDialogElement,
|
|
244
|
+
) {
|
|
245
|
+
this.setAttribute('open', '');
|
|
246
|
+
});
|
|
247
|
+
HTMLDialogElement.prototype.close = vi.fn(function (
|
|
248
|
+
this: HTMLDialogElement,
|
|
249
|
+
) {
|
|
250
|
+
this.removeAttribute('open');
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('dismisses on Escape by default', () => {
|
|
255
|
+
render(
|
|
256
|
+
<Popover content={<span>Content</span>} label="Test">
|
|
257
|
+
<button type="button">Open</button>
|
|
258
|
+
</Popover>,
|
|
259
|
+
);
|
|
260
|
+
const trigger = screen.getByRole('button', {name: 'Open'});
|
|
261
|
+
fireEvent.click(trigger);
|
|
262
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
263
|
+
|
|
264
|
+
fireEvent.keyDown(document, {key: 'Escape'});
|
|
265
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('stays open on Escape when hasEscapeDismiss is false', () => {
|
|
269
|
+
render(
|
|
270
|
+
<Popover
|
|
271
|
+
content={<span>Content</span>}
|
|
272
|
+
label="Test"
|
|
273
|
+
hasLightDismiss={false}
|
|
274
|
+
hasEscapeDismiss={false}>
|
|
275
|
+
<button type="button">Open</button>
|
|
276
|
+
</Popover>,
|
|
277
|
+
);
|
|
278
|
+
const trigger = screen.getByRole('button', {name: 'Open'});
|
|
279
|
+
fireEvent.click(trigger);
|
|
280
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
281
|
+
|
|
282
|
+
fireEvent.keyDown(document, {key: 'Escape'});
|
|
283
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('still dismisses on Escape when only light dismiss is off', () => {
|
|
287
|
+
render(
|
|
288
|
+
<Popover
|
|
289
|
+
content={<span>Content</span>}
|
|
290
|
+
label="Test"
|
|
291
|
+
hasLightDismiss={false}>
|
|
292
|
+
<button type="button">Open</button>
|
|
293
|
+
</Popover>,
|
|
294
|
+
);
|
|
295
|
+
const trigger = screen.getByRole('button', {name: 'Open'});
|
|
296
|
+
fireEvent.click(trigger);
|
|
297
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
298
|
+
|
|
299
|
+
fireEvent.keyDown(document, {key: 'Escape'});
|
|
300
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('switches to popover="manual" when hasLightDismiss is false', () => {
|
|
304
|
+
const {unmount} = render(
|
|
305
|
+
<Popover content={<span>Content</span>} label="Test">
|
|
306
|
+
<button type="button">Open</button>
|
|
307
|
+
</Popover>,
|
|
308
|
+
);
|
|
309
|
+
fireEvent.click(screen.getByRole('button', {name: 'Open'}));
|
|
310
|
+
expect(document.querySelector('[popover]')).toHaveAttribute(
|
|
311
|
+
'popover',
|
|
312
|
+
'auto',
|
|
313
|
+
);
|
|
314
|
+
unmount();
|
|
315
|
+
|
|
316
|
+
render(
|
|
317
|
+
<Popover
|
|
318
|
+
content={<span>Content</span>}
|
|
319
|
+
label="Test"
|
|
320
|
+
hasLightDismiss={false}>
|
|
321
|
+
<button type="button">Open</button>
|
|
322
|
+
</Popover>,
|
|
323
|
+
);
|
|
324
|
+
fireEvent.click(screen.getByRole('button', {name: 'Open'}));
|
|
325
|
+
expect(document.querySelector('[popover]')).toHaveAttribute(
|
|
326
|
+
'popover',
|
|
327
|
+
'manual',
|
|
328
|
+
);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('lets Escape fall through to a host Dialog when fully opted out', () => {
|
|
332
|
+
const onDialogOpenChange = vi.fn();
|
|
333
|
+
render(
|
|
334
|
+
<Dialog isOpen={true} onOpenChange={onDialogOpenChange} purpose="info">
|
|
335
|
+
<Popover
|
|
336
|
+
content={<span>Coachmark</span>}
|
|
337
|
+
label="Tip"
|
|
338
|
+
hasLightDismiss={false}
|
|
339
|
+
hasEscapeDismiss={false}>
|
|
340
|
+
<button type="button">Open tip</button>
|
|
341
|
+
</Popover>
|
|
342
|
+
</Dialog>,
|
|
343
|
+
);
|
|
344
|
+
const trigger = screen.getByRole('button', {name: 'Open tip'});
|
|
345
|
+
fireEvent.click(trigger);
|
|
346
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
347
|
+
|
|
348
|
+
// The Dialog listens for Escape on the dialog element, so fire from a
|
|
349
|
+
// node inside it. The popover registers no Escape handler, so
|
|
350
|
+
// hasActiveFocusTrapEscape() is false and the Dialog handles the press
|
|
351
|
+
// while the popover itself stays open.
|
|
352
|
+
fireEvent.keyDown(trigger, {key: 'Escape'});
|
|
353
|
+
expect(onDialogOpenChange).toHaveBeenCalledWith(false);
|
|
354
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
355
|
+
});
|
|
356
|
+
});
|
|
236
357
|
});
|
package/src/Popover/Popover.tsx
CHANGED
|
@@ -186,6 +186,24 @@ export interface PopoverProps extends Pick<
|
|
|
186
186
|
*/
|
|
187
187
|
hasAutoFocus?: boolean;
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Whether clicking outside dismisses the popover.
|
|
191
|
+
* Set to `false` for surfaces that should stay open until explicitly
|
|
192
|
+
* dismissed, like onboarding coachmarks or multi-step flows.
|
|
193
|
+
* @default true
|
|
194
|
+
*/
|
|
195
|
+
hasLightDismiss?: boolean;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Whether pressing Escape dismisses the popover.
|
|
199
|
+
*
|
|
200
|
+
* Only takes full effect together with `hasLightDismiss={false}`: with
|
|
201
|
+
* light dismiss on, the browser's native light dismiss also closes on
|
|
202
|
+
* Escape. Set both to `false` for explicit-dismiss-only surfaces.
|
|
203
|
+
* @default true
|
|
204
|
+
*/
|
|
205
|
+
hasEscapeDismiss?: boolean;
|
|
206
|
+
|
|
189
207
|
/**
|
|
190
208
|
* Test ID for the popover container.
|
|
191
209
|
*/
|
|
@@ -239,7 +257,7 @@ const styles = stylex.create({
|
|
|
239
257
|
* (immune to pressed-state transforms like `:active { scale(0.98) }`).
|
|
240
258
|
*
|
|
241
259
|
* Focus is trapped inside the popover when open.
|
|
242
|
-
* Supports light dismiss (click outside or Escape to close).
|
|
260
|
+
* Supports light dismiss by default (click outside or Escape to close).
|
|
243
261
|
*
|
|
244
262
|
* For hover-triggered overlays, use {@link HoverCard} instead.
|
|
245
263
|
*
|
|
@@ -277,6 +295,8 @@ export function Popover({
|
|
|
277
295
|
hasCloseButton,
|
|
278
296
|
closeButtonLabel,
|
|
279
297
|
hasAutoFocus,
|
|
298
|
+
hasLightDismiss = true,
|
|
299
|
+
hasEscapeDismiss = true,
|
|
280
300
|
xstyle,
|
|
281
301
|
className,
|
|
282
302
|
style,
|
|
@@ -299,7 +319,8 @@ export function Popover({
|
|
|
299
319
|
|
|
300
320
|
const popover = usePopover({
|
|
301
321
|
dialogLabel: label,
|
|
302
|
-
hasLightDismiss
|
|
322
|
+
hasLightDismiss,
|
|
323
|
+
hasEscapeDismiss,
|
|
303
324
|
hasCloseButton,
|
|
304
325
|
closeButtonLabel,
|
|
305
326
|
hasAutoFocus,
|
|
@@ -11,10 +11,13 @@ export const docs = {
|
|
|
11
11
|
{name: 'onHide', type: '() => void', description: 'Callback fired when the popover is hidden. Use this to return focus to the trigger when needed.'},
|
|
12
12
|
{name: 'xstyle', type: 'StyleXStyles', description: 'StyleX styles applied to the popover content wrapper, after the default surface styles.'},
|
|
13
13
|
{name: 'hasLightDismiss', type: 'boolean', description: 'Whether clicking outside dismisses the popover.', default: 'true'},
|
|
14
|
+
{name: 'hasEscapeDismiss', type: 'boolean', description: 'Whether pressing Escape dismisses the popover. Only takes full effect together with hasLightDismiss: false, since native light dismiss also closes on Escape.', default: 'true'},
|
|
14
15
|
{name: 'hasAutoFocus', type: 'boolean', description: 'Whether to automatically focus the first focusable element when opened.', default: 'true'},
|
|
15
16
|
{name: 'hasCloseButton', type: 'boolean', description: 'Whether to include a hidden close button that appears for keyboard users.', default: 'true'},
|
|
16
17
|
{name: 'closeButtonLabel', type: 'string', description: 'Accessible label for the hidden close button.', default: "'Close popover'"},
|
|
17
|
-
{name: 'dialogLabel', type: 'string', description: 'Accessible label for the popover dialog. Provide one when there is no visible title.'},
|
|
18
|
+
{name: 'dialogLabel', type: 'string', description: 'Accessible label for the popover dialog (only applies when role is "dialog"). Provide one when there is no visible title.'},
|
|
19
|
+
{name: 'role', type: "'dialog' | 'none'", description: 'ARIA role on the content wrapper. Use "dialog" for genuine dialog content; use "none" for listbox/menu popups whose own content role should be exposed and whose trigger keeps DOM focus.', default: "'dialog'"},
|
|
20
|
+
{name: 'isModal', type: 'boolean', description: 'Whether a dialog-role popover is modal (aria-modal). Only applies when role is "dialog".', default: 'true'},
|
|
18
21
|
{name: 'hasSurface', type: 'boolean', description: 'Whether to apply the default popover surface background, radius, and shadow.', default: 'true'},
|
|
19
22
|
],
|
|
20
23
|
returns: [
|
|
@@ -27,7 +30,7 @@ export const docs = {
|
|
|
27
30
|
{name: 'isOpen', type: 'boolean', description: 'Whether the popover is currently open.'},
|
|
28
31
|
{name: 'id', type: 'string', description: 'Unique ID for aria-describedby or aria-controls.'},
|
|
29
32
|
{name: 'render', type: '(children: ReactNode, props?: ContextRenderProps) => ReactNode', description: 'Render function for anchor-positioned popover content. Pass placement and alignment here.'},
|
|
30
|
-
{name: 'triggerProps', type: '{aria-haspopup: "dialog"; aria-expanded: boolean; aria-controls: string}', description: 'ARIA attributes to spread onto the trigger element.'},
|
|
33
|
+
{name: 'triggerProps', type: '{aria-haspopup: "dialog" | "true"; aria-expanded: boolean; aria-controls: string}', description: 'ARIA attributes to spread onto the trigger element. aria-haspopup reflects the popover role.'},
|
|
31
34
|
],
|
|
32
35
|
usage: {
|
|
33
36
|
description: 'Headless hook for click-triggered popovers with focus trapping. Combines useLayer with useFocusTrap, auto-focus, light dismiss, Escape handling, and an optional hidden close button for accessible dialog-like popover behavior. Use for custom interactive floating content that needs keyboard navigation.',
|
|
@@ -51,10 +54,13 @@ export const docsDense = {
|
|
|
51
54
|
onHide: 'fires when popover hides; use to return focus when needed.',
|
|
52
55
|
xstyle: 'StyleX styles for content wrapper, after default surface.',
|
|
53
56
|
hasLightDismiss: 'whether outside click dismisses popover.',
|
|
57
|
+
hasEscapeDismiss: 'whether Escape dismisses; full effect only w/ hasLightDismiss false.',
|
|
54
58
|
hasAutoFocus: 'whether first focusable element receives focus on open.',
|
|
55
59
|
hasCloseButton: 'whether hidden keyboard close button is included.',
|
|
56
60
|
closeButtonLabel: 'label for hidden close button.',
|
|
57
|
-
dialogLabel: 'accessible label for popover dialog.',
|
|
61
|
+
dialogLabel: 'accessible label for popover dialog (role="dialog" only).',
|
|
62
|
+
role: 'content wrapper ARIA role; "none" for listbox/menu popups.',
|
|
63
|
+
isModal: 'whether a dialog-role popover is modal (aria-modal).',
|
|
58
64
|
hasSurface: 'apply default surface background/radius/shadow.',
|
|
59
65
|
},
|
|
60
66
|
returnDescriptions: {
|
|
@@ -109,6 +109,19 @@ export interface UsePopoverOptions {
|
|
|
109
109
|
*/
|
|
110
110
|
hasLightDismiss?: boolean;
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Whether pressing Escape dismisses the popover.
|
|
114
|
+
*
|
|
115
|
+
* Takes effect together with `hasLightDismiss: false`: with light dismiss
|
|
116
|
+
* on, the native popover uses `popover="auto"`, whose browser-level light
|
|
117
|
+
* dismiss also closes on Escape, so Escape handling stays registered to
|
|
118
|
+
* keep topmost-only dismissal intact. Set both to `false` for
|
|
119
|
+
* explicit-dismiss-only surfaces like onboarding coachmarks.
|
|
120
|
+
*
|
|
121
|
+
* @default true
|
|
122
|
+
*/
|
|
123
|
+
hasEscapeDismiss?: boolean;
|
|
124
|
+
|
|
112
125
|
/**
|
|
113
126
|
* Whether to automatically focus the first focusable element when opened.
|
|
114
127
|
* @default true
|
|
@@ -130,10 +143,35 @@ export interface UsePopoverOptions {
|
|
|
130
143
|
|
|
131
144
|
/**
|
|
132
145
|
* Accessible label for the dialog.
|
|
133
|
-
* Required for screen readers to announce the dialog purpose
|
|
146
|
+
* Required for screen readers to announce the dialog purpose
|
|
147
|
+
* (only applies when `role` is `'dialog'`).
|
|
134
148
|
*/
|
|
135
149
|
dialogLabel?: string;
|
|
136
150
|
|
|
151
|
+
/**
|
|
152
|
+
* ARIA role stamped on the popover content wrapper.
|
|
153
|
+
*
|
|
154
|
+
* - `'dialog'` (default): the wrapper is a `role="dialog"` and, when
|
|
155
|
+
* `isModal` is true, carries `aria-modal`. Use for genuine dialog content.
|
|
156
|
+
* - `'none'`: the wrapper carries no role or `aria-modal`, so the popup's own
|
|
157
|
+
* content role (e.g. a child `role="listbox"` or `role="menu"`) is the
|
|
158
|
+
* exposed semantics. Use for comboboxes, listboxes, and menus — their
|
|
159
|
+
* trigger keeps DOM focus, so announcing an unnamed modal dialog around
|
|
160
|
+
* them is incorrect.
|
|
161
|
+
*
|
|
162
|
+
* @default 'dialog'
|
|
163
|
+
*/
|
|
164
|
+
role?: 'dialog' | 'none';
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Whether the dialog is modal (`aria-modal`). Only applies when `role` is
|
|
168
|
+
* `'dialog'`. Set to `false` for non-modal dialogs that do not inert the rest
|
|
169
|
+
* of the page.
|
|
170
|
+
*
|
|
171
|
+
* @default true
|
|
172
|
+
*/
|
|
173
|
+
isModal?: boolean;
|
|
174
|
+
|
|
137
175
|
/**
|
|
138
176
|
* Whether to apply the default popover surface (background, border-radius,
|
|
139
177
|
* box-shadow) to the content wrapper.
|
|
@@ -215,7 +253,7 @@ export interface UsePopoverReturn {
|
|
|
215
253
|
* ARIA attributes to spread on the trigger element
|
|
216
254
|
*/
|
|
217
255
|
triggerProps: {
|
|
218
|
-
'aria-haspopup': 'dialog';
|
|
256
|
+
'aria-haspopup': 'dialog' | 'true';
|
|
219
257
|
'aria-expanded': boolean;
|
|
220
258
|
'aria-controls': string;
|
|
221
259
|
};
|
|
@@ -228,7 +266,7 @@ export interface UsePopoverReturn {
|
|
|
228
266
|
* - `useLayer` for popover positioning using CSS anchor positioning
|
|
229
267
|
* - `useFocusTrap` for trapping focus within the popover content
|
|
230
268
|
* - Auto-focus first element on open
|
|
231
|
-
* - Escape key to close
|
|
269
|
+
* - Escape key to close (configurable via hasEscapeDismiss)
|
|
232
270
|
* - Hidden close button that reveals on focus for accessibility
|
|
233
271
|
*
|
|
234
272
|
* The render function automatically wraps your content in a focus trap container
|
|
@@ -261,19 +299,20 @@ export interface UsePopoverReturn {
|
|
|
261
299
|
* }
|
|
262
300
|
* ```
|
|
263
301
|
*/
|
|
264
|
-
export function usePopover(
|
|
265
|
-
options: UsePopoverOptions = {},
|
|
266
|
-
): UsePopoverReturn {
|
|
302
|
+
export function usePopover(options: UsePopoverOptions = {}): UsePopoverReturn {
|
|
267
303
|
const {
|
|
268
304
|
onShow,
|
|
269
305
|
onHide,
|
|
270
306
|
xstyle,
|
|
271
307
|
hasLightDismiss = true,
|
|
308
|
+
hasEscapeDismiss = true,
|
|
272
309
|
hasAutoFocus = true,
|
|
273
310
|
hasSurface = true,
|
|
274
311
|
hasCloseButton = true,
|
|
275
312
|
closeButtonLabel = 'Close popover',
|
|
276
313
|
dialogLabel,
|
|
314
|
+
role = 'dialog',
|
|
315
|
+
isModal = true,
|
|
277
316
|
} = options;
|
|
278
317
|
|
|
279
318
|
// Track the trigger element for returning focus
|
|
@@ -290,10 +329,12 @@ export function usePopover(
|
|
|
290
329
|
onHide,
|
|
291
330
|
});
|
|
292
331
|
|
|
293
|
-
// Focus trap for the popover content
|
|
332
|
+
// Focus trap for the popover content. Escape stays registered while light
|
|
333
|
+
// dismiss is on (native popover="auto" closes on Escape regardless), so a
|
|
334
|
+
// host Dialog keeps deferring to this trap instead of double-dismissing.
|
|
294
335
|
const {containerRef: contentRef, focusFirst} = useFocusTrap<HTMLDivElement>({
|
|
295
336
|
isActive: layer.isOpen,
|
|
296
|
-
onEscape: layer.hide,
|
|
337
|
+
onEscape: hasEscapeDismiss || hasLightDismiss ? layer.hide : undefined,
|
|
297
338
|
});
|
|
298
339
|
|
|
299
340
|
// Auto-focus first element when popover opens (unless skipped)
|
|
@@ -339,20 +380,35 @@ export function usePopover(
|
|
|
339
380
|
|
|
340
381
|
// ARIA attributes for the trigger
|
|
341
382
|
const triggerProps = {
|
|
342
|
-
'aria-haspopup':
|
|
383
|
+
'aria-haspopup':
|
|
384
|
+
role === 'dialog' ? ('dialog' as const) : ('true' as const),
|
|
343
385
|
'aria-expanded': layer.isOpen,
|
|
344
386
|
'aria-controls': layer.id,
|
|
345
387
|
};
|
|
346
388
|
|
|
389
|
+
// Dev-time guardrail: a dialog popover should always be labeled. Warn once
|
|
390
|
+
// per hook instance (in an effect) rather than on every render.
|
|
391
|
+
const warnedUnnamedDialogRef = useRef(false);
|
|
392
|
+
useEffect(() => {
|
|
393
|
+
if (role === 'dialog' && !dialogLabel && !warnedUnnamedDialogRef.current) {
|
|
394
|
+
warnedUnnamedDialogRef.current = true;
|
|
395
|
+
console.warn(
|
|
396
|
+
'usePopover: role="dialog" without a `dialogLabel` renders an unnamed ' +
|
|
397
|
+
'dialog. Pass `dialogLabel`, or use `role: "none"` for listbox/menu ' +
|
|
398
|
+
'popups whose content already carries its own role.',
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
}, [role, dialogLabel]);
|
|
402
|
+
|
|
347
403
|
// Wrapped render function that includes surface styles and optional hidden close button
|
|
348
404
|
const render = useCallback(
|
|
349
405
|
(children: ReactNode, props?: ContextRenderProps): ReactNode => {
|
|
350
406
|
return layer.render(
|
|
351
407
|
<div
|
|
352
408
|
ref={contentRef}
|
|
353
|
-
role=
|
|
354
|
-
aria-modal=
|
|
355
|
-
aria-label={dialogLabel}
|
|
409
|
+
role={role === 'dialog' ? 'dialog' : undefined}
|
|
410
|
+
aria-modal={role === 'dialog' && isModal ? true : undefined}
|
|
411
|
+
aria-label={role === 'dialog' ? dialogLabel : undefined}
|
|
356
412
|
{...stylex.props(
|
|
357
413
|
styles.contentWrapper,
|
|
358
414
|
hasSurface && styles.surface,
|
|
@@ -379,6 +435,8 @@ export function usePopover(
|
|
|
379
435
|
closeButtonLabel,
|
|
380
436
|
contentRef,
|
|
381
437
|
dialogLabel,
|
|
438
|
+
role,
|
|
439
|
+
isModal,
|
|
382
440
|
xstyle,
|
|
383
441
|
],
|
|
384
442
|
);
|