@primitiv-ui/react 0.1.28 → 0.1.30
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/README.md +19 -2
- package/package.json +6 -1
- package/src/AccessibleIcon/AccessibleIcon.tsx +32 -9
- package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +5 -0
- package/src/AccessibleIcon/types.ts +15 -2
- package/src/Accordion/Accordion.tsx +32 -11
- package/src/Accordion/README.md +2 -2
- package/src/Accordion/__tests__/Accordion.asChild.test.tsx +46 -0
- package/src/Accordion/__tests__/Accordion.basic-rendering.test.tsx +15 -0
- package/src/Accordion/__tests__/Accordion.disabled-items.test.tsx +42 -0
- package/src/Accordion/__tests__/Accordion.error-handling.test.tsx +33 -0
- package/src/Accordion/hooks/useAccordionRoot.ts +44 -7
- package/src/Accordion/hooks/useAccordionTrigger.ts +9 -1
- package/src/Accordion/types.ts +72 -21
- package/src/Alert/Alert.tsx +36 -7
- package/src/Alert/__tests__/Alert.test.tsx +5 -0
- package/src/Alert/types.ts +18 -2
- package/src/Avatar/Avatar.tsx +99 -15
- package/src/Avatar/__tests__/Avatar.basic-rendering.test.tsx +10 -0
- package/src/Avatar/__tests__/Avatar.fallback.test.tsx +30 -0
- package/src/Avatar/__tests__/Avatar.image-loading.test.tsx +35 -0
- package/src/Avatar/hooks/useAvatarImage.ts +16 -0
- package/src/Avatar/types.ts +15 -3
- package/src/Breadcrumb/Breadcrumb.tsx +139 -21
- package/src/Breadcrumb/README.md +47 -0
- package/src/Breadcrumb/__tests__/Breadcrumb.basic-rendering.test.tsx +11 -0
- package/src/Breadcrumb/__tests__/Breadcrumb.ellipsis.test.tsx +110 -0
- package/src/Breadcrumb/types.ts +73 -7
- package/src/Button/Button.tsx +2 -0
- package/src/Button/__tests__/Button.basic-rendering.test.tsx +6 -0
- package/src/Button/__tests__/Button.contract.test.tsx +1 -1
- package/src/Button/types.ts +21 -0
- package/src/Carousel/Carousel.tsx +268 -20
- package/src/Carousel/README.md +764 -87
- package/src/Carousel/__tests__/Carousel.autoplay-status.test.tsx +239 -0
- package/src/Carousel/__tests__/Carousel.drag-status.test.tsx +292 -0
- package/src/Carousel/__tests__/Carousel.dynamic-slides.test.tsx +38 -0
- package/src/Carousel/__tests__/Carousel.indicators.test.tsx +101 -0
- package/src/Carousel/__tests__/Carousel.infinite.test.tsx +1453 -0
- package/src/Carousel/__tests__/Carousel.instant-scroll.test.tsx +124 -0
- package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +90 -2
- package/src/Carousel/__tests__/Carousel.loop.test.tsx +163 -0
- package/src/Carousel/__tests__/Carousel.loopEngine.test.ts +77 -0
- package/src/Carousel/__tests__/Carousel.mouse-drag.test.tsx +504 -0
- package/src/Carousel/__tests__/Carousel.multi-slide-bounds.test.tsx +91 -0
- package/src/Carousel/__tests__/Carousel.orientation.test.tsx +207 -0
- package/src/Carousel/__tests__/Carousel.overscroll.test.tsx +532 -0
- package/src/Carousel/__tests__/Carousel.page-snap-points.test.tsx +50 -0
- package/src/Carousel/__tests__/Carousel.progress-text.test.tsx +76 -0
- package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +3 -6
- package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +2 -5
- package/src/Carousel/__tests__/Carousel.scroll-margin.test.tsx +167 -0
- package/src/Carousel/__tests__/Carousel.scroll-progress.test.tsx +518 -0
- package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +32 -11
- package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +237 -24
- package/src/Carousel/__tests__/Carousel.scroll-to-index.test.tsx +115 -0
- package/src/Carousel/__tests__/Carousel.slide-snap.test.tsx +172 -0
- package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +179 -1
- package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +91 -7
- package/src/Carousel/__tests__/Carousel.snap-type.test.tsx +35 -0
- package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +30 -5
- package/src/Carousel/__tests__/Carousel.translations.test.tsx +23 -0
- package/src/Carousel/__tests__/Carousel.wheel.test.tsx +160 -0
- package/src/Carousel/hooks/index.ts +1 -0
- package/src/Carousel/hooks/useCarouselLoop.ts +869 -0
- package/src/Carousel/hooks/useCarouselRoot.ts +338 -42
- package/src/Carousel/hooks/useCarouselSlide.ts +44 -9
- package/src/Carousel/hooks/useCarouselViewport.ts +649 -46
- package/src/Carousel/loopEngine.ts +54 -0
- package/src/Carousel/types.ts +458 -36
- package/src/Checkbox/Checkbox.tsx +11 -3
- package/src/Checkbox/__tests__/Checkbox.basic-rendering.test.tsx +14 -0
- package/src/Checkbox/hooks/useCheckboxInput.ts +4 -0
- package/src/Checkbox/types.ts +19 -0
- package/src/CheckboxCard/CheckboxCard.tsx +14 -5
- package/src/CheckboxCard/README.md +1 -1
- package/src/CheckboxCard/__tests__/CheckboxCard.basic-rendering.test.tsx +7 -0
- package/src/CheckboxCard/types.ts +65 -17
- package/src/Collapsible/Collapsible.tsx +49 -3
- package/src/Collapsible/README.md +41 -1
- package/src/Collapsible/__tests__/Collapsible.asChild.test.tsx +89 -0
- package/src/Collapsible/__tests__/Collapsible.basic-rendering.test.tsx +27 -0
- package/src/Collapsible/__tests__/Collapsible.collapsedHeight.test.tsx +140 -0
- package/src/Collapsible/hooks/useCollapsibleTrigger.ts +3 -1
- package/src/Collapsible/types.ts +89 -22
- package/src/Combobox/Combobox.tsx +508 -0
- package/src/Combobox/ComboboxContext.ts +23 -0
- package/src/Combobox/README.md +170 -0
- package/src/Combobox/__tests__/Combobox.asChild.test.tsx +62 -0
- package/src/Combobox/__tests__/Combobox.basic-rendering.test.tsx +16 -0
- package/src/Combobox/__tests__/Combobox.content.test.tsx +36 -0
- package/src/Combobox/__tests__/Combobox.controlled-state.test.tsx +88 -0
- package/src/Combobox/__tests__/Combobox.empty.test.tsx +42 -0
- package/src/Combobox/__tests__/Combobox.ids.test.tsx +66 -0
- package/src/Combobox/__tests__/Combobox.item.test.tsx +76 -0
- package/src/Combobox/__tests__/Combobox.keyboard-interaction.test.tsx +196 -0
- package/src/Combobox/__tests__/Combobox.light-dismiss.test.tsx +101 -0
- package/src/Combobox/__tests__/Combobox.query.test.tsx +105 -0
- package/src/Combobox/hooks/index.ts +1 -0
- package/src/Combobox/hooks/useComboboxRoot.ts +2 -0
- package/src/Combobox/index.ts +3 -0
- package/src/Combobox/types.ts +133 -0
- package/src/ContextMenu/ContextMenu.tsx +270 -4
- package/src/ContextMenu/README.md +1 -1
- package/src/ContextMenu/types.ts +148 -6
- package/src/DirectionProvider/DirectionProvider.tsx +41 -9
- package/src/DirectionProvider/README.md +4 -4
- package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +5 -0
- package/src/DirectionProvider/types.ts +28 -3
- package/src/Divider/Divider.tsx +24 -10
- package/src/Divider/__tests__/Divider.contract.test.tsx +1 -1
- package/src/Divider/__tests__/Divider.test.tsx +5 -0
- package/src/Divider/types.ts +10 -3
- package/src/Drawer/Drawer.tsx +315 -0
- package/src/Drawer/README.md +124 -0
- package/src/Drawer/__tests__/Drawer.behavior.test.tsx +100 -0
- package/src/Drawer/__tests__/Drawer.focus-trap.test.tsx +55 -0
- package/src/Drawer/__tests__/Drawer.rendering.test.tsx +111 -0
- package/src/Drawer/__tests__/Drawer.side.test.tsx +69 -0
- package/src/Drawer/__tests__/dialog-polyfill.ts +39 -0
- package/src/Drawer/index.ts +2 -0
- package/src/Drawer/types.ts +66 -0
- package/src/Dropdown/Dropdown.tsx +119 -2
- package/src/Dropdown/README.md +7 -5
- package/src/Dropdown/types.ts +241 -11
- package/src/EmptyState/EmptyState.tsx +74 -4
- package/src/EmptyState/README.md +2 -2
- package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +7 -2
- package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +3 -1
- package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +10 -0
- package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +3 -1
- package/src/EmptyState/types.ts +49 -6
- package/src/Field/Field.tsx +23 -0
- package/src/Field/README.md +1 -1
- package/src/Field/__tests__/Field.basic-rendering.test.tsx +11 -0
- package/src/Field/__tests__/Field.error-handling.test.tsx +23 -0
- package/src/Field/__tests__/Field.state-cascade.test.tsx +21 -0
- package/src/Field/hooks/__tests__/useFieldProps.test.tsx +104 -9
- package/src/Field/hooks/useFieldProps.ts +1 -1
- package/src/Field/types.ts +60 -12
- package/src/Fieldset/Fieldset.tsx +55 -19
- package/src/Fieldset/README.md +2 -2
- package/src/Fieldset/__tests__/Fieldset.basic-rendering.test.tsx +9 -0
- package/src/Fieldset/types.ts +20 -2
- package/src/Input/Input.tsx +15 -10
- package/src/Input/README.md +2 -2
- package/src/Input/__tests__/Input.basic-rendering.test.tsx +5 -0
- package/src/Input/types.ts +19 -2
- package/src/InputGroup/InputGroup.tsx +11 -3
- package/src/InputGroup/__tests__/InputGroup.basic-rendering.test.tsx +14 -0
- package/src/InputGroup/types.ts +26 -5
- package/src/Listbox/Listbox.tsx +475 -0
- package/src/Listbox/ListboxContext.ts +48 -0
- package/src/Listbox/README.md +248 -0
- package/src/Listbox/__tests__/Listbox.active-descendant.test.tsx +128 -0
- package/src/Listbox/__tests__/Listbox.asChild.test.tsx +91 -0
- package/src/Listbox/__tests__/Listbox.basic-rendering.test.tsx +16 -0
- package/src/Listbox/__tests__/Listbox.controlled-state.test.tsx +114 -0
- package/src/Listbox/__tests__/Listbox.disabled.test.tsx +90 -0
- package/src/Listbox/__tests__/Listbox.fixtures.ts +27 -0
- package/src/Listbox/__tests__/Listbox.group-label.test.tsx +97 -0
- package/src/Listbox/__tests__/Listbox.group.test.tsx +45 -0
- package/src/Listbox/__tests__/Listbox.keyboard-edge-cases.test.tsx +144 -0
- package/src/Listbox/__tests__/Listbox.keyboard-interaction.test.tsx +112 -0
- package/src/Listbox/__tests__/Listbox.modifier-keys.test.tsx +86 -0
- package/src/Listbox/__tests__/Listbox.multi-select-keyboard.test.tsx +368 -0
- package/src/Listbox/__tests__/Listbox.multiple-mode.test.tsx +91 -0
- package/src/Listbox/__tests__/Listbox.mutation-hardening.test.tsx +480 -0
- package/src/Listbox/__tests__/Listbox.orientation.test.tsx +59 -0
- package/src/Listbox/__tests__/Listbox.reading-direction.test.tsx +65 -0
- package/src/Listbox/__tests__/Listbox.reorder.test.tsx +78 -0
- package/src/Listbox/__tests__/Listbox.selection-follows-focus.test.tsx +64 -0
- package/src/Listbox/__tests__/Listbox.strict-context.test.tsx +21 -0
- package/src/Listbox/__tests__/Listbox.typeahead.test.tsx +123 -0
- package/src/Listbox/__tests__/Listbox.uncontrolled-state.test.tsx +48 -0
- package/src/Listbox/constants.ts +2 -0
- package/src/Listbox/hooks/index.ts +1 -0
- package/src/Listbox/hooks/useListboxRoot.ts +407 -0
- package/src/Listbox/index.ts +3 -0
- package/src/Listbox/types.ts +238 -0
- package/src/MillerColumns/MillerColumns.tsx +186 -45
- package/src/MillerColumns/README.md +90 -20
- package/src/MillerColumns/__tests__/MillerColumns.aria.test.tsx +45 -0
- package/src/MillerColumns/__tests__/MillerColumns.auto-scroll.test.tsx +4 -2
- package/src/MillerColumns/__tests__/MillerColumns.basic-rendering.test.tsx +18 -3
- package/src/MillerColumns/__tests__/MillerColumns.data-attributes.test.tsx +48 -0
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-interaction.test.tsx +35 -2
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-selection-state.test.tsx +96 -0
- package/src/MillerColumns/__tests__/MillerColumns.preview-panel.test.tsx +29 -4
- package/src/MillerColumns/__tests__/MillerColumns.preview-visibility.test.tsx +79 -0
- package/src/MillerColumns/__tests__/MillerColumns.resize.test.tsx +189 -0
- package/src/MillerColumns/__tests__/MillerColumns.styled-parts.test.tsx +143 -0
- package/src/MillerColumns/__tests__/MillerColumns.typeahead.test.tsx +104 -0
- package/src/MillerColumns/constants.ts +2 -0
- package/src/MillerColumns/hooks/useMillerColumnsColumn.ts +5 -2
- package/src/MillerColumns/hooks/useMillerColumnsItem.ts +29 -7
- package/src/MillerColumns/hooks/useMillerColumnsResizeHandle.ts +80 -10
- package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
- package/src/MillerColumns/index.ts +4 -0
- package/src/MillerColumns/types.ts +136 -30
- package/src/MillerColumns/utils.ts +69 -3
- package/src/Modal/Modal.tsx +35 -8
- package/src/Modal/README.md +24 -15
- package/src/Modal/__tests__/Modal.focus-trap.test.tsx +162 -0
- package/src/Modal/hooks/useModalContent.ts +32 -0
- package/src/Modal/types.ts +110 -29
- package/src/NavigationMenu/NavigationMenu.tsx +890 -0
- package/src/NavigationMenu/NavigationMenuContext.ts +67 -0
- package/src/NavigationMenu/README.md +355 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.anchor-positioning.test.tsx +132 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.asChild.test.tsx +73 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.basic-rendering.test.tsx +92 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.contract.test.tsx +45 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.controlled-state.test.tsx +134 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.error-handling.test.tsx +62 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.fixtures.tsx +79 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.forceMount.test.tsx +52 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.hover-interaction.test.tsx +254 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.indicator.test.tsx +252 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-interaction.test.tsx +294 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-navigation.test.tsx +126 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.link.test.tsx +139 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.motion.test.tsx +568 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.mouse-interaction.test.tsx +76 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.uncontrolled-state.test.tsx +30 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.viewport.test.tsx +113 -0
- package/src/NavigationMenu/constants.ts +5 -0
- package/src/NavigationMenu/hooks/index.ts +7 -0
- package/src/NavigationMenu/hooks/useNavigationMenuEntry.ts +33 -0
- package/src/NavigationMenu/hooks/useNavigationMenuIndicator.ts +70 -0
- package/src/NavigationMenu/hooks/useNavigationMenuLink.ts +72 -0
- package/src/NavigationMenu/hooks/useNavigationMenuRoot.ts +301 -0
- package/src/NavigationMenu/hooks/useNavigationMenuTopLevelEntry.ts +65 -0
- package/src/NavigationMenu/hooks/useNavigationMenuTrigger.ts +158 -0
- package/src/NavigationMenu/hooks/useNavigationMenuViewport.ts +101 -0
- package/src/NavigationMenu/index.ts +3 -0
- package/src/NavigationMenu/types.ts +259 -0
- package/src/NavigationMenu/utils.ts +89 -0
- package/src/Popover/Popover.tsx +427 -0
- package/src/Popover/PopoverContext.ts +13 -0
- package/src/Popover/README.md +106 -0
- package/src/Popover/__tests__/Popover.anchor.test.tsx +38 -0
- package/src/Popover/__tests__/Popover.asChild.test.tsx +160 -0
- package/src/Popover/__tests__/Popover.basic-rendering.test.tsx +106 -0
- package/src/Popover/__tests__/Popover.click-outside.test.tsx +149 -0
- package/src/Popover/__tests__/Popover.close.test.tsx +70 -0
- package/src/Popover/__tests__/Popover.content.test.tsx +58 -0
- package/src/Popover/__tests__/Popover.controlled-state.test.tsx +45 -0
- package/src/Popover/__tests__/Popover.error-handling.test.tsx +51 -0
- package/src/Popover/__tests__/Popover.focus.test.tsx +43 -0
- package/src/Popover/__tests__/Popover.keyboard-interaction.test.tsx +71 -0
- package/src/Popover/__tests__/Popover.mouse-interaction.test.tsx +69 -0
- package/src/Popover/__tests__/Popover.uncontrolled-state.test.tsx +44 -0
- package/src/Popover/hooks/index.ts +3 -0
- package/src/Popover/hooks/usePopoverContent.ts +98 -0
- package/src/Popover/hooks/usePopoverRoot.ts +84 -0
- package/src/Popover/hooks/usePopoverTrigger.ts +33 -0
- package/src/Popover/index.ts +2 -0
- package/src/Popover/types.ts +197 -0
- package/src/Portal/Portal.tsx +50 -10
- package/src/Portal/README.md +2 -2
- package/src/Portal/__tests__/Portal.basic-rendering.test.tsx +5 -0
- package/src/Portal/types.ts +5 -0
- package/src/Progress/Progress.tsx +33 -1
- package/src/Progress/README.md +1 -1
- package/src/Progress/__tests__/Progress.basic-rendering.test.tsx +10 -0
- package/src/Progress/__tests__/Progress.value.test.tsx +21 -0
- package/src/Progress/types.ts +20 -4
- package/src/Radio/Radio.tsx +10 -2
- package/src/Radio/__tests__/Radio.basic-rendering.test.tsx +14 -0
- package/src/Radio/hooks/useRadioRoot.ts +3 -0
- package/src/Radio/types.ts +20 -0
- package/src/RadioCard/RadioCard.tsx +11 -0
- package/src/RadioCard/__tests__/RadioCard.basic-rendering.test.tsx +8 -0
- package/src/RadioCard/__tests__/RadioCard.disabled-items.test.tsx +27 -0
- package/src/RadioCard/__tests__/RadioCard.keyboard-interaction.test.tsx +53 -0
- package/src/RadioCard/__tests__/RadioCard.ref-forwarding.test.tsx +54 -0
- package/src/RadioCard/__tests__/RadioCard.uncontrolled-state.test.tsx +21 -0
- package/src/RadioCard/hooks/useRadioCardRoot.ts +11 -0
- package/src/RadioCard/types.ts +95 -22
- package/src/RadioGroup/README.md +2 -2
- package/src/RadioGroup/RadioGroup.tsx +12 -1
- package/src/RadioGroup/__tests__/RadioGroup.basic-rendering.test.tsx +8 -0
- package/src/RadioGroup/__tests__/RadioGroup.disabled.test.tsx +27 -0
- package/src/RadioGroup/__tests__/RadioGroup.ref-forwarding.test.tsx +29 -0
- package/src/RadioGroup/__tests__/RadioGroup.roving-tabindex.test.tsx +31 -0
- package/src/RadioGroup/hooks/useRadioGroupRoot.ts +11 -0
- package/src/RadioGroup/types.ts +73 -9
- package/src/SegmentedControl/README.md +154 -0
- package/src/SegmentedControl/SegmentedControl.tsx +309 -0
- package/src/SegmentedControl/SegmentedControlContext.ts +28 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.asChild.test.tsx +50 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.basic-rendering.test.tsx +100 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.controlled-state.test.tsx +107 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled-keydown-guards.test.tsx +62 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled.test.tsx +151 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.error-handling.test.tsx +17 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.keyboard-interaction.test.tsx +117 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.orientation.test.tsx +54 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.reading-direction.test.tsx +56 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.ref-forwarding.test.tsx +45 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.roving-tabindex.test.tsx +104 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.uncontrolled-state.test.tsx +94 -0
- package/src/SegmentedControl/hooks/index.ts +2 -0
- package/src/SegmentedControl/hooks/useSegmentedControlContext.ts +1 -0
- package/src/SegmentedControl/hooks/useSegmentedControlRoot.ts +87 -0
- package/src/SegmentedControl/index.ts +2 -0
- package/src/SegmentedControl/types.ts +138 -0
- package/src/Select/README.md +122 -157
- package/src/Select/Select.tsx +596 -69
- package/src/Select/SelectContext.ts +38 -0
- package/src/Select/SelectItemIndicatorContext.ts +29 -0
- package/src/Select/__tests__/Select.asChild.test.tsx +2 -2
- package/src/Select/__tests__/Select.basic-rendering.test.tsx +22 -3
- package/src/Select/__tests__/Select.controlled-state.test.tsx +6 -6
- package/src/Select/__tests__/Select.data-attributes.test.tsx +4 -4
- package/src/Select/__tests__/Select.field-integration.test.tsx +11 -11
- package/src/Select/__tests__/Select.form.test.tsx +38 -0
- package/src/Select/__tests__/Select.group.test.tsx +6 -6
- package/src/Select/__tests__/Select.keyboard-edge.test.tsx +95 -0
- package/src/Select/__tests__/Select.keyboard.test.tsx +124 -0
- package/src/Select/__tests__/Select.mutation-hardening.test.tsx +317 -0
- package/src/Select/__tests__/Select.native-item.test.tsx +30 -0
- package/src/Select/__tests__/Select.open-close.test.tsx +57 -0
- package/src/Select/__tests__/Select.placeholder.test.tsx +7 -7
- package/src/Select/__tests__/Select.rich-asChild.test.tsx +60 -0
- package/src/Select/__tests__/Select.rich-mode.test.tsx +16 -0
- package/src/Select/__tests__/Select.selection.test.tsx +104 -0
- package/src/Select/__tests__/Select.separator.test.tsx +71 -0
- package/src/Select/__tests__/Select.strict-context.test.tsx +36 -0
- package/src/Select/__tests__/Select.typeahead.test.tsx +156 -0
- package/src/Select/__tests__/Select.value-mirror.test.tsx +240 -0
- package/src/Select/constants.ts +8 -0
- package/src/Select/hooks/index.ts +2 -0
- package/src/Select/hooks/useSelectContent.ts +149 -0
- package/src/Select/hooks/useSelectRoot.ts +149 -0
- package/src/Select/types.ts +199 -31
- package/src/SkipNav/README.md +3 -3
- package/src/SkipNav/SkipNav.tsx +72 -32
- package/src/SkipNav/__tests__/SkipNav.basic-rendering.test.tsx +6 -0
- package/src/SkipNav/types.ts +17 -9
- package/src/Slider/README.md +37 -7
- package/src/Slider/Slider.tsx +42 -4
- package/src/Slider/SliderContext.ts +28 -1
- package/src/Slider/types.ts +157 -9
- package/src/Slot/Slot.tsx +94 -19
- package/src/Slot/__tests__/Slot.test.tsx +112 -2
- package/src/Slot/composeEventHandlers.ts +26 -2
- package/src/Slot/types.ts +16 -0
- package/src/SplitButton/README.md +225 -0
- package/src/SplitButton/SplitButton.tsx +457 -0
- package/src/SplitButton/SplitButtonContext.ts +26 -0
- package/src/SplitButton/__tests__/SplitButton.accessibility.test.tsx +55 -0
- package/src/SplitButton/__tests__/SplitButton.asChild.test.tsx +51 -0
- package/src/SplitButton/__tests__/SplitButton.basic-rendering.test.tsx +57 -0
- package/src/SplitButton/__tests__/SplitButton.data-attributes.test.tsx +28 -0
- package/src/SplitButton/__tests__/SplitButton.disabled.test.tsx +79 -0
- package/src/SplitButton/__tests__/SplitButton.error-handling.test.tsx +29 -0
- package/src/SplitButton/__tests__/SplitButton.keyboard-interaction.test.tsx +56 -0
- package/src/SplitButton/__tests__/SplitButton.state-modes.test.tsx +68 -0
- package/src/SplitButton/index.ts +2 -0
- package/src/SplitButton/types.ts +186 -0
- package/src/Status/Status.tsx +36 -15
- package/src/Status/__tests__/Status.test.tsx +5 -0
- package/src/Status/types.ts +12 -1
- package/src/Switch/README.md +1 -1
- package/src/Switch/Switch.tsx +17 -4
- package/src/Switch/__tests__/Switch.basic-rendering.test.tsx +7 -0
- package/src/Switch/hooks/useSwitchRoot.ts +3 -0
- package/src/Switch/types.ts +49 -22
- package/src/Table/README.md +110 -8
- package/src/Table/Table.tsx +246 -16
- package/src/Table/TableExpandableContext.ts +7 -0
- package/src/Table/__tests__/Table.DetailRow.test.tsx +83 -0
- package/src/Table/__tests__/Table.ExpandTrigger.test.tsx +102 -0
- package/src/Table/__tests__/Table.Expandable.test.tsx +121 -0
- package/src/Table/types.ts +191 -17
- package/src/Tabs/README.md +4 -4
- package/src/Tabs/Tabs.tsx +13 -4
- package/src/Tabs/__tests__/Tabs.activation-mode.test.tsx +58 -0
- package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +15 -0
- package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +24 -0
- package/src/Tabs/__tests__/Tabs.disabled-tabs.test.tsx +36 -0
- package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +17 -0
- package/src/Tabs/hooks/useTabsContent.ts +5 -0
- package/src/Tabs/hooks/useTabsRoot.ts +29 -5
- package/src/Tabs/hooks/useTabsTrigger.ts +7 -2
- package/src/Tabs/types.ts +29 -4
- package/src/Textarea/Textarea.tsx +9 -1
- package/src/Textarea/__tests__/Textarea.basic-rendering.test.tsx +5 -0
- package/src/Textarea/types.ts +20 -3
- package/src/Toggle/Toggle.tsx +51 -13
- package/src/Toggle/__tests__/Toggle.basic-rendering.test.tsx +5 -0
- package/src/Toggle/types.ts +54 -4
- package/src/ToggleGroup/README.md +4 -4
- package/src/ToggleGroup/ToggleGroup.tsx +14 -1
- package/src/ToggleGroup/__tests__/ToggleGroup.asChild.test.tsx +20 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.basic-rendering.test.tsx +9 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.dynamic-items.test.tsx +70 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.error-handling.test.tsx +23 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.keyboard-interaction.test.tsx +23 -1
- package/src/ToggleGroup/__tests__/ToggleGroup.ref-forwarding.test.tsx +58 -0
- package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +21 -1
- package/src/ToggleGroup/types.ts +55 -2
- package/src/Tooltip/README.md +7 -7
- package/src/Tooltip/Tooltip.tsx +100 -22
- package/src/Tooltip/__tests__/Tooltip.basic-rendering.test.tsx +50 -0
- package/src/Tooltip/__tests__/Tooltip.error-handling.test.tsx +37 -0
- package/src/Tooltip/__tests__/Tooltip.escape-hatches.test.tsx +73 -0
- package/src/Tooltip/__tests__/Tooltip.keyboard-interaction.test.tsx +134 -0
- package/src/Tooltip/__tests__/Tooltip.skip-delay.test.tsx +216 -0
- package/src/Tooltip/__tests__/Tooltip.timer-coordination.test.tsx +223 -0
- package/src/Tooltip/hooks/__tests__/useTooltipProvider.test.tsx +40 -0
- package/src/Tooltip/hooks/useTooltipContent.ts +3 -0
- package/src/Tooltip/hooks/useTooltipProvider.ts +46 -8
- package/src/Tooltip/hooks/useTooltipRoot.ts +30 -6
- package/src/Tooltip/types.ts +89 -8
- package/src/Tree/README.md +69 -5
- package/src/Tree/Tree.tsx +188 -34
- package/src/Tree/__tests__/Tree.styled-wrapper.test.tsx +159 -0
- package/src/Tree/hooks/useTreePath.ts +33 -1
- package/src/Tree/index.ts +6 -1
- package/src/Tree/types.ts +54 -12
- package/src/Tree/utils.ts +46 -4
- package/src/VisuallyHidden/VisuallyHidden.tsx +33 -8
- package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +15 -1
- package/src/VisuallyHidden/types.ts +11 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useTypeahead.ts +95 -0
- package/src/index.ts +10 -0
- package/src/test/intersectionObserverPolyfill.ts +7 -0
- package/src/test/resizeObserverPolyfill.ts +80 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.reading.test.tsx +31 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.resilience.test.tsx +97 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.ssr.test.tsx +20 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.writing.test.tsx +72 -0
- package/src/useLocalStorage/index.ts +1 -0
- package/src/useLocalStorage/useLocalStorage.ts +140 -0
- package/src/useMediaQuery/README.md +66 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.matching.test.tsx +42 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.ssr.test.tsx +19 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.subscription.test.tsx +89 -0
- package/src/useMediaQuery/index.ts +1 -0
- package/src/useMediaQuery/useMediaQuery.ts +49 -0
- package/src/usePagination/README.md +170 -0
- package/src/usePagination/__tests__/usePagination.navigation.test.tsx +109 -0
- package/src/usePagination/__tests__/usePagination.page-count.test.tsx +56 -0
- package/src/usePagination/__tests__/usePagination.page-state.test.tsx +87 -0
- package/src/usePagination/__tests__/usePagination.range.test.tsx +82 -0
- package/src/usePagination/__tests__/usePagination.slice.test.tsx +59 -0
- package/src/usePagination/__tests__/usePagination.windowing.test.tsx +68 -0
- package/src/usePagination/index.ts +1 -0
- package/src/usePagination/usePagination.ts +292 -0
- package/src/utils/focusable.ts +15 -0
- package/src/utils/getKeyToActionMap.ts +1 -1
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import "./dialog-polyfill";
|
|
2
|
+
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
|
|
5
|
+
import { Drawer } from "../Drawer";
|
|
6
|
+
|
|
7
|
+
describe("Drawer — rendering & structure", () => {
|
|
8
|
+
it("Trigger renders a <button> with dialog ARIA", () => {
|
|
9
|
+
// Arrange / Act
|
|
10
|
+
render(
|
|
11
|
+
<Drawer.Root>
|
|
12
|
+
<Drawer.Trigger>Open</Drawer.Trigger>
|
|
13
|
+
</Drawer.Root>,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// Assert
|
|
17
|
+
const trigger = screen.getByRole("button", { name: "Open" });
|
|
18
|
+
expect(trigger).toHaveAttribute("type", "button");
|
|
19
|
+
expect(trigger).toHaveAttribute("aria-haspopup", "dialog");
|
|
20
|
+
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("Content renders a native <dialog> when open", () => {
|
|
24
|
+
// Arrange / Act
|
|
25
|
+
render(
|
|
26
|
+
<Drawer.Root defaultOpen>
|
|
27
|
+
<Drawer.Content data-testid="drawer">body</Drawer.Content>
|
|
28
|
+
</Drawer.Root>,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// Assert
|
|
32
|
+
const dialog = screen.getByTestId("drawer");
|
|
33
|
+
expect(dialog).toBeInTheDocument();
|
|
34
|
+
expect(dialog.tagName).toBe("DIALOG");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("Title and Description render and auto-wire the dialog's ARIA", () => {
|
|
38
|
+
// Arrange / Act
|
|
39
|
+
render(
|
|
40
|
+
<Drawer.Root defaultOpen>
|
|
41
|
+
<Drawer.Content data-testid="drawer">
|
|
42
|
+
<Drawer.Title>Filters</Drawer.Title>
|
|
43
|
+
<Drawer.Description>Narrow the results.</Drawer.Description>
|
|
44
|
+
</Drawer.Content>
|
|
45
|
+
</Drawer.Root>,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Assert
|
|
49
|
+
const title = screen.getByRole("heading", { name: "Filters", level: 2 });
|
|
50
|
+
const description = screen.getByText("Narrow the results.");
|
|
51
|
+
const dialog = screen.getByTestId("drawer");
|
|
52
|
+
expect(dialog).toHaveAttribute("aria-labelledby", title.id);
|
|
53
|
+
expect(dialog).toHaveAttribute("aria-describedby", description.id);
|
|
54
|
+
expect(description.tagName).toBe("P");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("Portal escapes to document.body and Overlay is a decorative sibling", () => {
|
|
58
|
+
// Arrange / Act
|
|
59
|
+
render(
|
|
60
|
+
<div data-testid="host">
|
|
61
|
+
<Drawer.Root defaultOpen>
|
|
62
|
+
<Drawer.Portal>
|
|
63
|
+
<Drawer.Overlay data-testid="overlay" />
|
|
64
|
+
<Drawer.Content data-testid="drawer">body</Drawer.Content>
|
|
65
|
+
</Drawer.Portal>
|
|
66
|
+
</Drawer.Root>
|
|
67
|
+
</div>,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Assert
|
|
71
|
+
const overlay = screen.getByTestId("overlay");
|
|
72
|
+
expect(overlay).toHaveAttribute("aria-hidden", "true");
|
|
73
|
+
expect(overlay).toHaveAttribute("data-state", "open");
|
|
74
|
+
// portalled out of the host wrapper, onto document.body
|
|
75
|
+
expect(screen.getByTestId("host")).not.toContainElement(
|
|
76
|
+
screen.getByTestId("drawer"),
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("Close renders a <button>", () => {
|
|
81
|
+
// Arrange / Act
|
|
82
|
+
render(
|
|
83
|
+
<Drawer.Root defaultOpen>
|
|
84
|
+
<Drawer.Content>
|
|
85
|
+
<Drawer.Close>Done</Drawer.Close>
|
|
86
|
+
</Drawer.Content>
|
|
87
|
+
</Drawer.Root>,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Assert
|
|
91
|
+
expect(screen.getByRole("button", { name: "Done" })).toHaveAttribute(
|
|
92
|
+
"type",
|
|
93
|
+
"button",
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("forwards asChild on the Trigger to the consumer element", () => {
|
|
98
|
+
// Arrange / Act
|
|
99
|
+
render(
|
|
100
|
+
<Drawer.Root>
|
|
101
|
+
<Drawer.Trigger asChild>
|
|
102
|
+
<a href="/cart">Cart</a>
|
|
103
|
+
</Drawer.Trigger>
|
|
104
|
+
</Drawer.Root>,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Assert
|
|
108
|
+
const link = screen.getByRole("link", { name: "Cart" });
|
|
109
|
+
expect(link).toHaveAttribute("aria-haspopup", "dialog");
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import "./dialog-polyfill";
|
|
2
|
+
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
|
|
5
|
+
import { Drawer } from "../Drawer";
|
|
6
|
+
import type { DrawerSide } from "../types";
|
|
7
|
+
|
|
8
|
+
const SIDES: DrawerSide[] = ["top", "right", "bottom", "left"];
|
|
9
|
+
|
|
10
|
+
describe("Drawer.Content — side axis", () => {
|
|
11
|
+
it("defaults data-side to 'right' when side is omitted", () => {
|
|
12
|
+
// Arrange / Act
|
|
13
|
+
render(
|
|
14
|
+
<Drawer.Root defaultOpen>
|
|
15
|
+
<Drawer.Content data-testid="drawer">body</Drawer.Content>
|
|
16
|
+
</Drawer.Root>,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Assert
|
|
20
|
+
expect(screen.getByTestId("drawer")).toHaveAttribute("data-side", "right");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it.each(SIDES)(
|
|
24
|
+
"emits data-side='%s' on the dialog",
|
|
25
|
+
(side) => {
|
|
26
|
+
// Arrange / Act
|
|
27
|
+
render(
|
|
28
|
+
<Drawer.Root defaultOpen>
|
|
29
|
+
<Drawer.Content data-testid="drawer" side={side}>
|
|
30
|
+
body
|
|
31
|
+
</Drawer.Content>
|
|
32
|
+
</Drawer.Root>,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Assert
|
|
36
|
+
expect(screen.getByTestId("drawer")).toHaveAttribute("data-side", side);
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
it("does not leak the `side` prop as a raw attribute on the dialog", () => {
|
|
41
|
+
// Arrange / Act
|
|
42
|
+
render(
|
|
43
|
+
<Drawer.Root defaultOpen>
|
|
44
|
+
<Drawer.Content data-testid="drawer" side="left">
|
|
45
|
+
body
|
|
46
|
+
</Drawer.Content>
|
|
47
|
+
</Drawer.Root>,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Assert
|
|
51
|
+
expect(screen.getByTestId("drawer")).not.toHaveAttribute("side");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("keeps data-state alongside data-side", () => {
|
|
55
|
+
// Arrange / Act
|
|
56
|
+
render(
|
|
57
|
+
<Drawer.Root defaultOpen>
|
|
58
|
+
<Drawer.Content data-testid="drawer" side="bottom">
|
|
59
|
+
body
|
|
60
|
+
</Drawer.Content>
|
|
61
|
+
</Drawer.Root>,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Assert
|
|
65
|
+
const dialog = screen.getByTestId("drawer");
|
|
66
|
+
expect(dialog).toHaveAttribute("data-side", "bottom");
|
|
67
|
+
expect(dialog).toHaveAttribute("data-state", "open");
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal scoped polyfill for the native <dialog> element in jsdom 29.
|
|
3
|
+
*
|
|
4
|
+
* jsdom does not implement showModal() / close() on HTMLDialogElement, so
|
|
5
|
+
* integration tests that render Drawer.Content (a native <dialog>, via
|
|
6
|
+
* Modal.Content) need a shim that:
|
|
7
|
+
* - toggles the `open` attribute (which is what .open reflects)
|
|
8
|
+
* - dispatches the native `close` event on close()
|
|
9
|
+
*
|
|
10
|
+
* The Drawer suite drives open/close through the trigger, the Close button,
|
|
11
|
+
* and the imperative API — the Esc/`cancel` and click-outside paths are
|
|
12
|
+
* Modal's behaviour and are covered by Modal's own suite, so this shim stays
|
|
13
|
+
* minimal. Mirrors Modal's scoped polyfill — imported explicitly where needed
|
|
14
|
+
* rather than installed globally, so other components keep exercising the real
|
|
15
|
+
* DOM.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
type DialogProto = HTMLDialogElement & { returnValue: string };
|
|
19
|
+
|
|
20
|
+
const proto = HTMLDialogElement.prototype as DialogProto;
|
|
21
|
+
|
|
22
|
+
if (typeof proto.showModal !== "function") {
|
|
23
|
+
proto.showModal = function showModal(this: HTMLDialogElement) {
|
|
24
|
+
this.setAttribute("open", "");
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof proto.close !== "function") {
|
|
29
|
+
proto.close = function close(this: HTMLDialogElement, returnValue?: string) {
|
|
30
|
+
if (!this.hasAttribute("open")) return;
|
|
31
|
+
this.removeAttribute("open");
|
|
32
|
+
if (returnValue !== undefined) {
|
|
33
|
+
(this as DialogProto).returnValue = String(returnValue);
|
|
34
|
+
}
|
|
35
|
+
this.dispatchEvent(new Event("close"));
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Ref } from "react";
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
ModalCloseProps,
|
|
5
|
+
ModalContentProps,
|
|
6
|
+
ModalDescriptionProps,
|
|
7
|
+
ModalImperativeApi,
|
|
8
|
+
ModalOverlayProps,
|
|
9
|
+
ModalPortalProps,
|
|
10
|
+
ModalRootProps,
|
|
11
|
+
ModalTitleProps,
|
|
12
|
+
ModalTriggerProps,
|
|
13
|
+
} from "../Modal/types";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Which edge the drawer slides in from.
|
|
17
|
+
*
|
|
18
|
+
* - `"top"` / `"bottom"` — a horizontal sheet spanning the viewport width.
|
|
19
|
+
* - `"left"` / `"right"` — a vertical panel spanning the viewport height.
|
|
20
|
+
*/
|
|
21
|
+
export type DrawerSide = "top" | "right" | "bottom" | "left";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Imperative handle exposed on `Drawer.Root`'s `ref`, letting callers open
|
|
25
|
+
* and close the drawer programmatically. Behaviour is inherited from
|
|
26
|
+
* {@link ModalImperativeApi | Modal} — a drawer is a Modal that slides from an edge.
|
|
27
|
+
*/
|
|
28
|
+
export type DrawerImperativeApi = ModalImperativeApi;
|
|
29
|
+
|
|
30
|
+
/** Props for `Drawer.Root`, in either the controlled or uncontrolled mode. */
|
|
31
|
+
export type DrawerRootProps = ModalRootProps;
|
|
32
|
+
|
|
33
|
+
/** Props for `Drawer.Trigger` — a `<button>` that opens the drawer. */
|
|
34
|
+
export type DrawerTriggerProps = ModalTriggerProps;
|
|
35
|
+
|
|
36
|
+
/** Props for `Drawer.Portal` — renders its children into `container`. */
|
|
37
|
+
export type DrawerPortalProps = ModalPortalProps;
|
|
38
|
+
|
|
39
|
+
/** Props for `Drawer.Overlay` — the click-outside backdrop. */
|
|
40
|
+
export type DrawerOverlayProps = ModalOverlayProps;
|
|
41
|
+
|
|
42
|
+
/** Props for `Drawer.Title` — supplies the drawer's accessible name. */
|
|
43
|
+
export type DrawerTitleProps = ModalTitleProps;
|
|
44
|
+
|
|
45
|
+
/** Props for `Drawer.Description` — supplies the drawer's accessible description. */
|
|
46
|
+
export type DrawerDescriptionProps = ModalDescriptionProps;
|
|
47
|
+
|
|
48
|
+
/** Props for `Drawer.Close` — a `<button>` that closes the drawer. */
|
|
49
|
+
export type DrawerCloseProps = ModalCloseProps;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Props for `Drawer.Content` — the native `<dialog>` props plus the
|
|
53
|
+
* drawer-specific {@link DrawerContentProps.side | `side`} axis.
|
|
54
|
+
*/
|
|
55
|
+
export type DrawerContentProps = ModalContentProps & {
|
|
56
|
+
/** Ref to the underlying native `<dialog>` element. */
|
|
57
|
+
ref?: Ref<HTMLDialogElement>;
|
|
58
|
+
/**
|
|
59
|
+
* Which edge the drawer slides in from. Emitted verbatim as `data-side`
|
|
60
|
+
* on the `<dialog>`, which the styled layer keys off to position and
|
|
61
|
+
* animate the panel against that edge. Purely presentational — it does
|
|
62
|
+
* not change any behaviour, focus, or ARIA.
|
|
63
|
+
* @default "right"
|
|
64
|
+
*/
|
|
65
|
+
side?: DrawerSide;
|
|
66
|
+
};
|
|
@@ -81,7 +81,7 @@ import { MENUITEM_SELECTOR } from "./constants";
|
|
|
81
81
|
* const [open, setOpen] = useState(false);
|
|
82
82
|
*
|
|
83
83
|
* <Dropdown.Root open={open} onOpenChange={setOpen}>
|
|
84
|
-
*
|
|
84
|
+
* ...
|
|
85
85
|
* </Dropdown.Root>
|
|
86
86
|
* ```
|
|
87
87
|
*/
|
|
@@ -121,6 +121,8 @@ DropdownRoot.displayName = "DropdownRoot";
|
|
|
121
121
|
* component). All ARIA attributes and event handlers are merged onto the
|
|
122
122
|
* child following the {@link Slot} composition rules.
|
|
123
123
|
*
|
|
124
|
+
* @extends HTMLButtonElement
|
|
125
|
+
*
|
|
124
126
|
* @example With an anchor via `asChild`
|
|
125
127
|
* ```tsx
|
|
126
128
|
* <Dropdown.Trigger asChild>
|
|
@@ -180,6 +182,17 @@ DropdownTrigger.displayName = "DropdownTrigger";
|
|
|
180
182
|
* so `ArrowDown` past a {@link DropdownSubTrigger | `Dropdown.SubTrigger`}
|
|
181
183
|
* lands on the next sibling item in the parent rather than getting
|
|
182
184
|
* stuck on a non-focusable item inside a closed sub-popover.
|
|
185
|
+
*
|
|
186
|
+
* @extends HTMLMenuElement
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```tsx
|
|
190
|
+
* <Dropdown.Content>
|
|
191
|
+
* <Dropdown.Item onSelect={rename}>Rename</Dropdown.Item>
|
|
192
|
+
* <Dropdown.Separator />
|
|
193
|
+
* <Dropdown.Item onSelect={remove}>Delete</Dropdown.Item>
|
|
194
|
+
* </Dropdown.Content>
|
|
195
|
+
* ```
|
|
183
196
|
*/
|
|
184
197
|
export function DropdownContent({
|
|
185
198
|
children,
|
|
@@ -218,6 +231,18 @@ DropdownContent.displayName = "DropdownContent";
|
|
|
218
231
|
*
|
|
219
232
|
* Disabled items receive `aria-disabled="true"` and are skipped by arrow
|
|
220
233
|
* navigation, typeahead, and activation handlers.
|
|
234
|
+
*
|
|
235
|
+
* @extends HTMLLIElement
|
|
236
|
+
*
|
|
237
|
+
* @example Keep the menu open after selecting
|
|
238
|
+
* ```tsx
|
|
239
|
+
* <Dropdown.Item onSelect={(event) => {
|
|
240
|
+
* copyToClipboard();
|
|
241
|
+
* event.preventDefault();
|
|
242
|
+
* }}>
|
|
243
|
+
* Copy link
|
|
244
|
+
* </Dropdown.Item>
|
|
245
|
+
* ```
|
|
221
246
|
*/
|
|
222
247
|
export function DropdownItem({
|
|
223
248
|
children,
|
|
@@ -248,6 +273,15 @@ DropdownItem.displayName = "DropdownItem";
|
|
|
248
273
|
* A visual separator between groups of items. Renders a `<li role="separator">`
|
|
249
274
|
* by default; pass `asChild` to render any element with separator semantics.
|
|
250
275
|
* Non-interactive — skipped by focus, arrow navigation, and typeahead.
|
|
276
|
+
*
|
|
277
|
+
* @extends HTMLLIElement
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```tsx
|
|
281
|
+
* <Dropdown.Item>Cut</Dropdown.Item>
|
|
282
|
+
* <Dropdown.Separator />
|
|
283
|
+
* <Dropdown.Item>Paste</Dropdown.Item>
|
|
284
|
+
* ```
|
|
251
285
|
*/
|
|
252
286
|
export function DropdownSeparator({
|
|
253
287
|
asChild = false,
|
|
@@ -275,6 +309,17 @@ DropdownSeparator.displayName = "DropdownSeparator";
|
|
|
275
309
|
* wired automatically via `aria-labelledby`. Nest a `Dropdown.Label` as the
|
|
276
310
|
* first child to provide the accessible name; screen readers will announce
|
|
277
311
|
* the group when arrowing into it.
|
|
312
|
+
*
|
|
313
|
+
* @extends HTMLLIElement
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```tsx
|
|
317
|
+
* <Dropdown.Group>
|
|
318
|
+
* <Dropdown.Label>Sort by</Dropdown.Label>
|
|
319
|
+
* <Dropdown.Item>Name</Dropdown.Item>
|
|
320
|
+
* <Dropdown.Item>Date</Dropdown.Item>
|
|
321
|
+
* </Dropdown.Group>
|
|
322
|
+
* ```
|
|
278
323
|
*/
|
|
279
324
|
export function DropdownGroup({
|
|
280
325
|
children,
|
|
@@ -307,6 +352,16 @@ DropdownGroup.displayName = "DropdownGroup";
|
|
|
307
352
|
*
|
|
308
353
|
* Renders a `<li>` by default; pass `asChild` to render any element. A
|
|
309
354
|
* caller-supplied `id` takes precedence over the auto-generated one.
|
|
355
|
+
*
|
|
356
|
+
* @extends HTMLLIElement
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```tsx
|
|
360
|
+
* <Dropdown.Group>
|
|
361
|
+
* <Dropdown.Label>Actions</Dropdown.Label>
|
|
362
|
+
* <Dropdown.Item>Duplicate</Dropdown.Item>
|
|
363
|
+
* </Dropdown.Group>
|
|
364
|
+
* ```
|
|
310
365
|
*/
|
|
311
366
|
export function DropdownLabel({
|
|
312
367
|
id,
|
|
@@ -350,6 +405,18 @@ DropdownLabel.displayName = "DropdownLabel";
|
|
|
350
405
|
* context and exposes `data-state` for styling.
|
|
351
406
|
*
|
|
352
407
|
* Disabled items receive `aria-disabled="true"` and no-op on activation.
|
|
408
|
+
*
|
|
409
|
+
* @extends HTMLLIElement
|
|
410
|
+
*
|
|
411
|
+
* @example Controlled checkbox item
|
|
412
|
+
* ```tsx
|
|
413
|
+
* <Dropdown.CheckboxItem checked={showGrid} onCheckedChange={setShowGrid}>
|
|
414
|
+
* <Dropdown.ItemIndicator>
|
|
415
|
+
* <CheckIcon />
|
|
416
|
+
* </Dropdown.ItemIndicator>
|
|
417
|
+
* Show grid
|
|
418
|
+
* </Dropdown.CheckboxItem>
|
|
419
|
+
* ```
|
|
353
420
|
*/
|
|
354
421
|
export function DropdownCheckboxItem({
|
|
355
422
|
children,
|
|
@@ -425,6 +492,22 @@ DropdownCheckboxItem.displayName = "DropdownCheckboxItem";
|
|
|
425
492
|
* - **Uncontrolled** — pass `defaultValue` (or omit for no initial selection).
|
|
426
493
|
* Optional `onValueChange` observes selections.
|
|
427
494
|
* - **Controlled** — pass `value` *and* `onValueChange` together.
|
|
495
|
+
*
|
|
496
|
+
* @extends HTMLLIElement
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* ```tsx
|
|
500
|
+
* <Dropdown.RadioGroup value={sort} onValueChange={setSort}>
|
|
501
|
+
* <Dropdown.RadioItem value="name">
|
|
502
|
+
* <Dropdown.ItemIndicator>•</Dropdown.ItemIndicator>
|
|
503
|
+
* Name
|
|
504
|
+
* </Dropdown.RadioItem>
|
|
505
|
+
* <Dropdown.RadioItem value="date">
|
|
506
|
+
* <Dropdown.ItemIndicator>•</Dropdown.ItemIndicator>
|
|
507
|
+
* Date
|
|
508
|
+
* </Dropdown.RadioItem>
|
|
509
|
+
* </Dropdown.RadioGroup>
|
|
510
|
+
* ```
|
|
428
511
|
*/
|
|
429
512
|
export function DropdownRadioGroup({
|
|
430
513
|
defaultValue,
|
|
@@ -476,6 +559,16 @@ DropdownRadioGroup.displayName = "DropdownRadioGroup";
|
|
|
476
559
|
* and exposes `data-state` for styling.
|
|
477
560
|
*
|
|
478
561
|
* Disabled items receive `aria-disabled="true"` and no-op on activation.
|
|
562
|
+
*
|
|
563
|
+
* @extends HTMLLIElement
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* ```tsx
|
|
567
|
+
* <Dropdown.RadioItem value="compact">
|
|
568
|
+
* <Dropdown.ItemIndicator>•</Dropdown.ItemIndicator>
|
|
569
|
+
* Compact
|
|
570
|
+
* </Dropdown.RadioItem>
|
|
571
|
+
* ```
|
|
479
572
|
*/
|
|
480
573
|
export function DropdownRadioItem({
|
|
481
574
|
children,
|
|
@@ -555,6 +648,8 @@ DropdownRadioItem.displayName = "DropdownRadioItem";
|
|
|
555
648
|
* the DOM node mounted in both states, which is handy when animating the
|
|
556
649
|
* indicator in and out via CSS transitions or a React animation library.
|
|
557
650
|
*
|
|
651
|
+
* @extends HTMLSpanElement
|
|
652
|
+
*
|
|
558
653
|
* @example
|
|
559
654
|
* ```tsx
|
|
560
655
|
* <Dropdown.CheckboxItem checked={showBookmarks} onCheckedChange={setShowBookmarks}>
|
|
@@ -683,6 +778,18 @@ DropdownSub.displayName = "DropdownSub";
|
|
|
683
778
|
*
|
|
684
779
|
* Disabled triggers receive `aria-disabled="true"` and ignore both click
|
|
685
780
|
* and the open arrow key.
|
|
781
|
+
*
|
|
782
|
+
* @extends HTMLLIElement
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* ```tsx
|
|
786
|
+
* <Dropdown.Sub>
|
|
787
|
+
* <Dropdown.SubTrigger>Share</Dropdown.SubTrigger>
|
|
788
|
+
* <Dropdown.SubContent>
|
|
789
|
+
* <Dropdown.Item>Email link</Dropdown.Item>
|
|
790
|
+
* </Dropdown.SubContent>
|
|
791
|
+
* </Dropdown.Sub>
|
|
792
|
+
* ```
|
|
686
793
|
*/
|
|
687
794
|
export function DropdownSubTrigger({
|
|
688
795
|
children,
|
|
@@ -749,6 +856,16 @@ DropdownSubTrigger.displayName = "DropdownSubTrigger";
|
|
|
749
856
|
* `ArrowLeft` in `"ltr"`, `ArrowRight` in `"rtl"`. All other keys bubble
|
|
750
857
|
* to the parent {@link DropdownContent | `Dropdown.Content`} so arrow
|
|
751
858
|
* navigation and typeahead apply to the submenu's items.
|
|
859
|
+
*
|
|
860
|
+
* @extends HTMLMenuElement
|
|
861
|
+
*
|
|
862
|
+
* @example
|
|
863
|
+
* ```tsx
|
|
864
|
+
* <Dropdown.SubContent>
|
|
865
|
+
* <Dropdown.Item>Project A</Dropdown.Item>
|
|
866
|
+
* <Dropdown.Item>Project B</Dropdown.Item>
|
|
867
|
+
* </Dropdown.SubContent>
|
|
868
|
+
* ```
|
|
752
869
|
*/
|
|
753
870
|
export function DropdownSubContent({
|
|
754
871
|
children,
|
|
@@ -843,7 +960,7 @@ export type TDropdownCompound = typeof DropdownRoot & {
|
|
|
843
960
|
* styles ship.
|
|
844
961
|
*
|
|
845
962
|
* The default export is the `Root`; sub-components are attached as static
|
|
846
|
-
* properties (`Dropdown.Trigger`, `Dropdown.Content`,
|
|
963
|
+
* properties (`Dropdown.Trigger`, `Dropdown.Content`, ...).
|
|
847
964
|
*/
|
|
848
965
|
const DropdownCompound: TDropdownCompound = Object.assign(DropdownRoot, {
|
|
849
966
|
Root: DropdownRoot,
|
package/src/Dropdown/README.md
CHANGED
|
@@ -213,7 +213,7 @@ submenu, which is unfocusable. While focus lives inside an open
|
|
|
213
213
|
<Dropdown.Group>
|
|
214
214
|
<Dropdown.Label>File</Dropdown.Label>
|
|
215
215
|
<Dropdown.Item>New</Dropdown.Item>
|
|
216
|
-
<Dropdown.Item>Open
|
|
216
|
+
<Dropdown.Item>Open...</Dropdown.Item>
|
|
217
217
|
</Dropdown.Group>
|
|
218
218
|
<Dropdown.Separator />
|
|
219
219
|
<Dropdown.Group>
|
|
@@ -249,7 +249,7 @@ the component's):
|
|
|
249
249
|
|
|
250
250
|
```css
|
|
251
251
|
/* Open state on the menu panel */
|
|
252
|
-
[role="menu"]
|
|
252
|
+
[role="menu"]:popover-open {
|
|
253
253
|
animation: fade-in var(--primitiv-motion-duration-control) var(--primitiv-motion-easing-enter);
|
|
254
254
|
}
|
|
255
255
|
|
|
@@ -274,9 +274,11 @@ the component's):
|
|
|
274
274
|
}
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
The
|
|
278
|
-
|
|
279
|
-
state-driven styling.
|
|
277
|
+
The popover API exposes the open state as the **`:popover-open` pseudo-class**,
|
|
278
|
+
not as an attribute — combine it with the standard ARIA attributes for
|
|
279
|
+
state-driven styling. (`data-popover-open` appears in this package's tests
|
|
280
|
+
because the jsdom popover polyfill mirrors the state to an attribute; no browser
|
|
281
|
+
sets it, so do not style against it.)
|
|
280
282
|
|
|
281
283
|
`data-highlighted` is present on `Item`, `CheckboxItem`, `RadioItem`, and
|
|
282
284
|
`SubTrigger` while the item has pointer focus (mouseenter). On `SubTrigger`
|