Skip to content

feat: positioning, actionsRef, list and form options across primitives - #2306

Merged
kotAPI merged 19 commits into
mainfrom
parity/4-api
Nov 4, 2026
Merged

kotAPI merged 19 commits into
mainfrom
parity/4-api

Conversation

@kotAPI

@kotAPI kotAPI commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

API additions across the primitives, plus two bug fixes and a clearer release announcement.

Positioning (Tooltip, HoverCard, Popover Content, menu Roots, Select/Combobox/Autocomplete Root): anchor (element, virtual element, ref or function), positionMethod, collisionAvoidance (flip/shift/none per axis), sticky, disableAnchorTracking, arrowPadding.

Imperative actions: actionsRef with close() on Dialog, AlertDialog, Popover, Tooltip, HoverCard, menus, Select, Combobox and NavigationMenu; validate() on Field and Form.

Lists: filter (or null), limit, locale, readOnly, form, inputRef, autoComplete, finalFocus, highlightItemOnHover, onItemHighlighted, loop; Combobox.useFilter / Autocomplete.useFilter; new Select.Label, Combobox.Status, Autocomplete.Status; Autocomplete autoHighlight, openOnInputClick, submitOnItemClick, mode.

Form controls: Checkbox indeterminate, uncheckedValue; Switch uncheckedValue; form / inputRef on Checkbox, Switch, RadioGroup, Slider, NumberField, OTPField. Slider thumbCollisionBehavior, format/locale, largeStep, thumb getAriaLabel/getAriaValueText. NumberField allowOutOfRange, snapOnStep. OTPField mask, normalizeValue, onValueInvalid, inputMode, autoComplete, OTPField.Separator. Field controlled touched/dirty, Field.Control onValueChange.

Other: Tooltip disabled, disableHoverablePopup, Trigger closeOnClick; HoverCard onOpenChange details and per-trigger delays; Popover per-trigger openOnHover/delays; menus highlightItemOnHover, onItemHighlighted, closeParentOnEsc, finalFocus, Arrow part; NavigationMenu delay, closeDelay, orientation, transitions, onOpenChangeComplete, disabled Trigger, Link active/closeOnClick; Toolbar focusableWhenDisabled; Drawer Provider/Indent/IndentBackground; Tree expanded/defaultExpanded/onExpandedChange and RTL arrows; ToggleGroup multiple.

Fixes

  • Escape in a submenu closed the whole menu; it now closes only the submenu and returns focus to its trigger item (closeParentOnEsc keeps the old behaviour).
  • A required OTPField never blocked form submission (the value sat in a hidden input, which browsers don't validate).

Release announcement: the Discord post groups changes (Breaking changes / New / Fixes), links each to its PR, shortens long entries, drops docs-only ones, and ends with an install line and npm / changelog / docs links. The broken README summary, changelog-file, repo and timestamp fields are gone. Preview with DRY_RUN=1 PKG_NAME=@radui/ui PKG_VERSION=1.1.4 REPO=rad-ui/ui node .github/scripts/announce-release.mjs.

Gates: tsc, eslint, 2307 tests, build, exports check, Storybook build + 10 browser tests, docs build against this package (305 pages). Changesets included; docs rows follow in the docs PR after the release.

kotAPI added 18 commits November 4, 2026 07:08
Tooltip.Content takes anchor (element, virtual element, ref or function),
positionMethod, collisionAvoidance, sticky, arrowPadding and
disableAnchorTracking, built on shared positioning helpers. Tooltip.Root
takes disabled and disableHoverablePopup; Tooltip.Trigger takes
closeOnClick (default true), and a disabled trigger doesn't open it.
HoverCard.Content, Popover.Content and the menu Root take anchor,
positionMethod, collisionAvoidance, sticky and disableAnchorTracking (and
arrowPadding where there is an arrow). HoverCard onOpenChange gets details
with a reason and cancel(); its triggers take delay/closeDelay. Popover
triggers take openOnHover/delay/closeDelay. Menus take highlightItemOnHover,
onItemHighlighted and closeParentOnEsc; Escape in a submenu now closes only
that submenu and returns focus to its trigger item.
…ptions

The shared list primitive takes filter (or null), limit, locale,
readOnly, form, inputRef, highlightItemOnHover, onItemHighlighted, loop,
and the positioning options (anchor, positionMethod, collisionAvoidance,
disableAnchorTracking, boolean sticky). The default filter ignores case
and accents; Combobox.useFilter and Autocomplete.useFilter expose the
matchers. Autocomplete takes autoHighlight (default off, so Enter keeps
typed text), openOnInputClick, submitOnItemClick and mode.
Checkbox: indeterminate, uncheckedValue, form, inputRef. Switch:
uncheckedValue, form, inputRef. RadioGroup: form, inputRef. Form reset
follows a form outside the tree. Slider: thumbCollisionBehavior
(none/push/swap), format/locale value text, largeStep, form; thumbs take
getAriaLabel, getAriaValueText and inputRef.
… required OTP

NumberField takes allowOutOfRange, snapOnStep, form and inputRef.
OTPField takes mask, normalizeValue, onValueInvalid, inputMode,
autoComplete and form, and gains OTPField.Separator. A required OTPField
now blocks submission until every slot is filled: the code sat in a
hidden input, which browsers never validate.
Dialog, AlertDialog, Popover, Tooltip, HoverCard, menus, Select and
Combobox take actionsRef with close() (reason 'imperative-action').
Field takes actionsRef with validate(), controlled touched and dirty;
Field.Control takes onValueChange. Form takes actionsRef with
validate(name?).
Root takes delay, closeDelay, orientation (vertical opens panels with
ArrowRight, ArrowLeft in RTL), onOpenChangeComplete and actionsRef.
Content plays enter/exit transitions (data-starting-style /
data-ending-style) and takes forceMount. A disabled Trigger doesn't
open on hover or keys. Link takes active (aria-current) and
closeOnClick.
Disabled toolbar items can stay in the arrow-key order, announced as
disabled and ignoring presses (Input becomes read-only).
Drawer.Provider tracks whether any drawer inside is open; Drawer.Indent
and Drawer.IndentBackground get data-active then, and the default theme
eases the page back (respects reduced motion).
Tree.Root takes expanded / defaultExpanded / onExpandedChange (keys are
item id, value or label) and dir; in RTL ArrowLeft expands and
ArrowRight collapses. Checklist tests added for RadioCards,
CheckboxCards and TextArea (keyboard, RTL, forms, Field).
Changes are grouped (Breaking changes / New / Fixes), each linked to its
PR, long entries cut to their first sentence, docs-only entries left
out, with an install line and npm / changelog / docs links. Drops the
broken README summary, the changelog-file and repo fields and the
timestamp. The embed colour follows the biggest change. Moved to
.github/scripts/announce-release.mjs, which can preview with DRY_RUN=1.
Menu Content and the Select/Combobox Root take finalFocus (trigger by
default, false, a ref or a function). Select/Combobox take autoComplete
for the hidden control; their Separator takes orientation. ToggleGroup
takes multiple as a shorthand for type="multiple".
@changeset-bot

changeset-bot Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2953f76

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@radui/ui Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 125 files, which is 25 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 520093bf-cd68-4333-b285-c8e65ce4247c
Commits

Reviewing files that changed from the base of the PR and between 07e6783 and 2953f76.

Files selected for processing: 125
  • .changeset/actions-ref.md
  • .changeset/drawer-indent.md
  • .changeset/floating-anchor-collision.md
  • .changeset/form-control-options.md
  • .changeset/hover-card-details-delays.md
  • .changeset/list-filtering-forms.md
  • .changeset/menu-highlight-escape.md
  • .changeset/navigation-menu-options.md
  • .changeset/otp-field-options.md
  • .changeset/toggle-group-multiple.md
  • .changeset/toolbar-focusable-disabled.md
  • .changeset/tooltip-disabled-close-on-click.md
  • .changeset/tree-expansion-rtl.md
  • .github/scripts/announce-release.mjs
  • .github/workflows/release.yml
  • knowledge/primitive-quality.md
  • src/components/ui/Autocomplete/Autocomplete.tsx
  • src/components/ui/Autocomplete/contexts/AutocompleteRootContext.tsx
  • src/components/ui/Autocomplete/fragments/AutocompleteInput.tsx
  • src/components/ui/Autocomplete/fragments/AutocompleteRoot.tsx
  • src/components/ui/Autocomplete/fragments/AutocompleteStatus.tsx
  • src/components/ui/Autocomplete/tests/Autocomplete.options.test.tsx
  • src/components/ui/Autocomplete/tests/Autocomplete.test.tsx
  • src/components/ui/Combobox/Combobox.tsx
  • src/components/ui/Combobox/fragments/ComboboxStatus.tsx
  • src/components/ui/Combobox/tests/Combobox.options.test.tsx
  • src/components/ui/ContextMenu/ContextMenu.tsx
  • src/components/ui/ContextMenu/fragments/ContextMenuArrow.tsx
  • src/components/ui/Drawer/Drawer.tsx
  • src/components/ui/Drawer/context/DrawerProviderContext.tsx
  • src/components/ui/Drawer/drawer.clarity.scss
  • src/components/ui/Drawer/fragments/DrawerIndent.tsx
  • src/components/ui/Drawer/fragments/DrawerIndentBackground.tsx
  • src/components/ui/Drawer/fragments/DrawerProvider.tsx
  • src/components/ui/Drawer/fragments/DrawerRoot.tsx
  • src/components/ui/Drawer/tests/Drawer.indent.test.tsx
  • src/components/ui/DropdownMenu/DropdownMenu.tsx
  • src/components/ui/DropdownMenu/fragments/DropdownMenuArrow.tsx
  • src/components/ui/DropdownMenu/tests/DropdownMenu.options.test.tsx
  • src/components/ui/Field/fragments/FieldControl.tsx
  • src/components/ui/Field/fragments/FieldRoot.tsx
  • src/components/ui/Form/Form.tsx
  • src/components/ui/Form/contexts/FormContext.tsx
  • src/components/ui/HoverCard/contexts/HoverCardContext.tsx
  • src/components/ui/HoverCard/contexts/hoverCardHandleControls.ts
  • src/components/ui/HoverCard/fragments/HoverCardContent.tsx
  • src/components/ui/HoverCard/fragments/HoverCardRoot.tsx
  • src/components/ui/HoverCard/fragments/HoverCardTrigger.tsx
  • src/components/ui/HoverCard/tests/HoverCard.options.test.tsx
  • src/components/ui/Menubar/Menubar.tsx
  • src/components/ui/Menubar/fragments/MenubarArrow.tsx
  • src/components/ui/NavigationMenu/contexts/NavigationMenuRootContext.tsx
  • src/components/ui/NavigationMenu/fragments/NavigationMenuContent.tsx
  • src/components/ui/NavigationMenu/fragments/NavigationMenuItem.tsx
  • src/components/ui/NavigationMenu/fragments/NavigationMenuLink.tsx
  • src/components/ui/NavigationMenu/fragments/NavigationMenuRoot.tsx
  • src/components/ui/NavigationMenu/fragments/NavigationMenuTrigger.tsx
  • src/components/ui/NavigationMenu/tests/NavigationMenu.options.test.tsx
  • src/components/ui/NumberField/contexts/NumberFieldContext.tsx
  • src/components/ui/NumberField/fragments/NumberFieldInput.tsx
  • src/components/ui/NumberField/fragments/NumberFieldRoot.tsx
  • src/components/ui/NumberField/tests/NumberField.options.test.tsx
  • src/components/ui/OTPField/OTPField.tsx
  • src/components/ui/OTPField/contexts/OTPFieldContext.tsx
  • src/components/ui/OTPField/fragments/OTPFieldInput.tsx
  • src/components/ui/OTPField/fragments/OTPFieldRoot.tsx
  • src/components/ui/OTPField/fragments/OTPFieldSeparator.tsx
  • src/components/ui/OTPField/tests/OTPField.options.test.tsx
  • src/components/ui/Popover/tests/Popover.options.test.tsx
  • src/components/ui/Select/Select.tsx
  • src/components/ui/Select/contexts/SelectRootContext.tsx
  • src/components/ui/Select/fragments/SelectLabel.tsx
  • src/components/ui/Select/fragments/SelectRoot.tsx
  • src/components/ui/Select/fragments/SelectTrigger.tsx
  • src/components/ui/Select/select.clarity.scss
  • src/components/ui/Select/tests/Select.label.test.tsx
  • src/components/ui/Slider/context/SliderContext.tsx
  • src/components/ui/Slider/fragments/SliderRoot.tsx
  • src/components/ui/Slider/fragments/SliderThumb.tsx
  • src/components/ui/Slider/utils/sliderMath.ts
  • src/components/ui/Switch/fragments/SwitchRoot.tsx
  • src/components/ui/ToggleGroup/fragments/ToggleGroupRoot.tsx
  • src/components/ui/Toolbar/fragments/ToolbarButton.tsx
  • src/components/ui/Toolbar/fragments/ToolbarInput.tsx
  • src/components/ui/Toolbar/tests/Toolbar.focusableWhenDisabled.test.tsx
  • src/components/ui/Tooltip/context/TooltipContext.tsx
  • src/components/ui/Tooltip/fragments/TooltipContent.tsx
  • src/components/ui/Tooltip/fragments/TooltipRoot.tsx
  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
  • src/components/ui/Tooltip/tests/Tooltip.options.test.tsx
  • src/components/ui/Tree/contexts/TreeContext.tsx
  • src/components/ui/Tree/fragments/TreeItem.tsx
  • src/components/ui/Tree/fragments/TreeRoot.tsx
  • src/components/ui/Tree/tests/Tree.expansion.test.tsx
  • src/components/ui/__tests__/actionsRef.test.tsx
  • src/components/ui/__tests__/checklist.choiceGroups.test.tsx
  • src/components/ui/__tests__/formControlOptions.test.tsx
  • src/components/ui/__tests__/smallOptions.test.tsx
  • src/core/hooks/useFilter/index.ts
  • src/core/hooks/useFloatingAnchor/index.ts
  • src/core/hooks/usePopupActions/index.ts
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveRoot.tsx
  • src/core/primitives/Combobox/ComboboxPrimitive.tsx
  • src/core/primitives/Combobox/contexts/ComboboxPrimitiveContext.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveClear.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveContent.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveRoot.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveSeparator.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveStatus.tsx
  • src/core/primitives/Combobox/fragments/ComboboxPrimitiveTrigger.tsx
  • src/core/primitives/Dialog/fragments/DialogPrimitiveRoot.tsx
  • src/core/primitives/Menu/MenuPrimitive.tsx
  • src/core/primitives/Menu/contexts/MenuPrimitiveRootContext.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveArrow.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveContent.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveRoot.tsx
  • src/core/primitives/Popover/context/PopoverPrimitiveContext.tsx
  • src/core/primitives/Popover/fragments/PopoverPrimitiveContent.tsx
  • src/core/primitives/Popover/fragments/PopoverPrimitiveRoot.tsx
  • src/core/primitives/Popover/fragments/PopoverPrimitiveTrigger.tsx
  • src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveRoot.tsx
  • src/core/utils/filter.ts
  • src/core/utils/focusTarget.ts
  • src/core/utils/openChangeDetails.ts
  • src/core/utils/placement.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Coverage

This report compares the PR with the base branch. "Δ" shows how the PR affects each metric.

Metric PR Δ
Statements 88.63% +0.15%
Branches 75.73% +0.50%
Functions 83% +0.23%
Lines 90.32% +0.15%

Coverage improved or stayed the same. Great job!

Run npm run coverage:ci locally for detailed reports and target untested areas to raise these numbers.

@kotAPI
kotAPI merged commit befc825 into main Nov 4, 2026
14 of 15 checks passed
@kotAPI
kotAPI deleted the parity/4-api branch November 4, 2026 04:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant