npm / @ariakit/react
@ariakit/react
What changed in @ariakit/react 0.4, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-18.
6 breaking3 security10 new APIs and options14 performance7 behavior and defaults94 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli init@ariakit/react 0.4134 changes
Breaking changes 6
Nested portals render inside a fullscreen element when an element inside a parent portal enters fullscreen.
A belonging ComboboxPopover now takes focus whenever it opens, including when opened with defaultOpen or programmatically while focus is elsewhere.
Passing undefined to a component prop now behaves like omitting it, preserving the value the component computes for itself.
Dialog scrolls its initially focused element only far enough to become visible instead of centering it.
Mounted but hidden popovers skip position auto-updates unless a custom updatePosition callback is provided, reducing listeners, observers, and positioning work.
Updated packages to target ES2018 instead of ES2017, which may affect runtime compatibility requirements.
Security 3
An own __proto__ prop can no longer replace the merged props object's prototype in rendered Role elements.
Field names with __proto__ or constructor path segments are ignored, preventing form state objects from being corrupted through prototype replacement.
Release artifacts now include npm trusted publishing provenance, which developers can use to verify their origin.
New APIs and options 10
Composite widgets set data-focus on the active item while DOM focus stays on the composite, enabling focus styling for virtual and hover focus.
Composite stores and stores for Combobox, Menu, Menubar, Radio, Select, Tab, and Toolbar now expose the composite element state.
This option controls whether arrow key navigation can move focus to the composite element.
Composite stores and stores for Combobox, Menu, Menubar, Radio, Select, Tab, and Toolbar now expose this method.
The Combobox store now exposes inputElement state and its setter.
The Combobox store now exposes labelElement state and its setter.
The Combobox store now exposes selectElement state and its setter.
The Combobox store now exposes selectLabelElement state and its setter.
The new value component exposes whether its closest SelectItem is selected through a required function child.
Composite items and derived components accept an explicit typeahead label, or an empty string to exclude an item from matching.
Performance 14
In a 243-option benchmark, restoring the full list after clearing the filter with one Combobox store reduced scripting time by 50% and total time by 43% compared with separate Select and Combobox stores.
React component mount performance improved by 12–21% in browser benchmarks.
Store performance improved across targeted benchmarks, reaching up to 49× the previous throughput.
Arrow-key navigation with roving tabindex no longer re-renders the Composite component, reducing scripting cost on large collections.
The composite store's down function scans rendered items without copying arrays in the most common cases.
The composite store's next function scans rendered items without copying arrays in the most common cases.
The composite store's previous function scans rendered items without copying arrays in the most common cases.
The composite store's up function scans rendered items without copying arrays in the most common cases.
FormControl and components built on it avoid redundant form store subscriptions and item lookups while fields update.
Menu renders less when items re-register without changing the initial focus target.
Rendering performance is improved.
Opening dialogs uses fewer tree walks, store subscriptions, and focus checks; layout work also moves to the layout phase to reduce recalculations and apply scroll locking before the first paint.
Default description tooltip anchors no longer re-render when the tooltip content id changes.
Adds an associated panel lookup to improve performance when resolving controlled panels.
Behavior and default changes 7
Menu placement is settled when its store is created. Menus whose parent becomes vertical later, or whose store is linked from outside the parent, remain below their items; pass placement to control it.
A modal Dialog’s visually hidden fallback dismiss button now renders next to the popup, still inside the modal context, so it is no longer an owned element of the popup.
Dialog and components built on it keep a mounted disclosure trigger as the opener when shown programmatically, positioning content against it and returning focus to it on close.
Descendants can stop propagation of Escape to dismiss a nested widget without hiding the enclosing Dialog or inherited component; handled events are also stopped at the component boundary.
Setting disabled on a RadioGroup now disables descendant Radio components, including radios rendered as custom elements.
The CSS variable is now defined only in the fallback path for browsers without scrollbar-gutter support; use a length fallback in calc() when targeting those browsers.
When portalRef changes identity, it now re-fires against the same portal node instead of destroying and recreating the node and remounting portal content.
Fixes and other changes 94
Hidden dismiss buttons in earlier modal dialogs stay disabled behind later modal popups, including when the dialog moves out of a portal or loses its dismiss button.
Requesting fullscreen on document.documentElement no longer moves default portal containers from document.body to html.
Elements inside a portal can enter fullscreen without throwing a HierarchyRequestError.
Button, Checkbox, and similar components no longer copy inherited enumerable Object.prototype properties onto the rendered element.
Button, Checkbox, and similar components no longer treat values carried by a directly passed __proto__ prop as props they were never given.
A popup that opens outside the viewport is scrolled into view when it takes focus; setting autoFocusOnShow to false prevents the focus and scroll.
ComboboxSelect no longer reports aria-expanded="false" while its popup is open.
The initially selected item is now centered when the popup opens.
ComboboxSelect and Combobox no longer move DOM focus off the collapsed control and into their popup.
Combobox, Select, and Menu no longer scroll the page while their popup is being positioned, unless page movement is needed to bring an item into view.
Dialog and components built on it no longer overwrite the element assigned with setDisclosureElement when they open.
Delayed auto-focus no longer pulls focus back after it has moved outside the dialog.
Focusable components now receive data-focus-visible on modified navigation keys such as Alt+ArrowDown and Ctrl+Home.
Focusable components no longer treat Safari's Option+Tab navigation as a pointer interaction and now receive data-focus-visible when focused that way.
Menu preserves DOM focus and brings a logical item into view when React replaces its element while the popup is positioning.
Hover focus no longer scrolls partially visible menubar and submenu items or the menu under the pointer.
Focus and scroll no longer move into a popup before a custom updatePosition that calls the supplied default function has finished its own work.
Checkbox and other components composed with render now preserve computed props when a render element receives undefined.
Multi-selectable Combobox components now submit selected values to forms when a name is provided.
Interactions with persistent elements across open shadow roots no longer close the component before it receives focus.
Sibling modal dialogs rendered in their default portals no longer make each other inert when opened in the same render.
Collection store lookups now resolve controlled items added after store creation when no live item is registered, allowing Select typeahead to update its value with unmounted options.
Composite widgets clear stale focus-visible state and warn in development when virtual focus is used with a non-focusable composite element.
Published packages now include their build output.
Store subscriptions now respond consistently to updates made with NaN keys.
Dialog close now waits for the backdrop exit transition to end, preventing its fade-out from being skipped or cut short.
Highlighting now covers exactly matched characters when Unicode normalization changes string length, without detaching combining marks from base letters.
For non-native elements, the pressed state clears when focus is lost while Space is held; bubbled Space keyups and prevented keyups no longer leave the element pressed or dispatch an unintended synthetic click.
With virtual focus enabled, focus received before the composite element is available now redirects to the composite element instead of remaining stuck on the item.
Passing NaN to aria-posinset or aria-setsize no longer causes a maximum update depth error.
Rendering inside a CompositeRow that receives aria-posinset no longer crashes with a rowId initialization error.
The focusOnMove prop is now respected on SelectList and components built on it.
Focusing, clicking, or right-clicking returned elements no longer closes the dialog before it has received focus.
The arrow no longer detaches from its anchor in RTL contexts when the popover flips or changes placement while open.
Portal no longer leaks duplicate portal containers in React development StrictMode.
Arrow-key selection now delivers a real change event with event.target.checked already true, matching pointer and Space selection.
Native radio onClick handlers now fire when arrow keys select a radio, matching native radio group behavior.
Closed Select arrow-key navigation now skips items without a value correctly, including when focusLoop wraps, avoiding page freezes.
Tab now becomes the active item on the first setSelectedId call after a SelectPopover or ComboboxPopover containing tabs opens or toggles.
A reused panel now reruns its tabbable-children check when tabId changes and updates its tabindex to join or leave the tab sequence as needed.
Composing Enter keydowns in nested text fields no longer cancel IME commits or move focus back to the container.
Snapshot values are compared with Object.is, fixing maximum update depth errors involving NaN and covering direct consumers of the hook.
Inline autocomplete no longer produces misspelled completion values for decomposed Unicode input.
Scroll behavior works for elements rendered inside a same-origin iframe.
An onMouseDown handler's event.preventDefault() is now honored before focus moves to the Combobox input.
With virtual focus disabled, non-paste Ctrl/Cmd character shortcuts now preserve focus and the combobox value, while paste shortcuts still route to the input.
Overlapping user input matches are rendered without duplicated text.
Base-element arrow key navigation now works in RTL composites, including Toolbar and TabList.
Keyboard paging works for elements rendered inside a same-origin iframe.
An explicit orientation prop is now honored instead of being replaced by the composite store-derived default; this also fixes ToolbarSeparator, MenuSeparator, SelectSeparator, and ComboboxSeparator.
A portaled Dialog reopened with a non-focusable element before its first focusable child now receives focus correctly.
When invalid fields mount out of registration order, Form focuses the first invalid field in document order.
With resetOnSubmit set to false, item changes after a successful submission no longer steal focus into an invalid field; autoFocusOnSubmit focuses the first invalid field only after a failed submission.
FormLabel no longer focuses a hidden element instead of the visible control.
Pushing into arrays now focuses the newly added field whether the array already has values or starts empty.
Pressing Escape closes the topmost nested card even when focus is on another element; this also applies to components built on Dialog.
Hovercard stays open when hovering content rendered inside an open shadow root; this also applies to Tooltip and Menu.
Menubar and menu bar stores now reflect navigation updates immediately before initialization.
Boolean fields now initialize from defaultChecked and controlled checked props when the menu store has no default value.
A portaled Popover reopened with a non-focusable element before its first focusable child now receives focus correctly.
When tabbing back into a group after an unchecked Radio received focus, focus now moves to the checked Radio.
Typeahead now skips disabled offscreen SelectItem placeholders.
Text fields rendered inside same-origin iframes are detected correctly, fixing Composite keyboard navigation and preventing Command and Combobox from treating them as non-text fields.
Pressing Backspace or Delete on a focused container with an empty text field no longer steals focus from the field on the next typed character.
Absent symbol keys on names values now resolve to undefined, so symbol probes no longer throw; coerce a name before rendering or inspecting it outside Ariakit props.
submit and validate no longer stall while the document is hidden because browsers pause requestAnimationFrame in background tabs.
Avoids passing invalid function children to React while unchecked.
The development error message now names the correct component.
The active state no longer gets stuck when Space is released while Meta is held or when the element becomes disabled between keydown and keyup.
Typeahead text from one composite no longer affects another composite on the same page.
Stale nested dialog effects no longer restore page accessibility state while a newer effect is active.
Resets outside-interaction focus tracking when reused dialogs reopen.
Unmount timing now uses the longest per-property transition or animation end time and ignores unmatched durations or delays, preventing content from staying mounted longer than necessary.
No longer incorrectly matches sibling array fields with prefix-sharing names or throws when field names contain regular expression special characters.
No longer incorrectly matches sibling array fields with prefix-sharing names or throws when field names contain regular expression special characters.
Nested hovercards no longer reinstall document mousemove listeners when they mount or unmount.
Stops forwarding
defaultCheckedto rendered elements.Ignores stale asynchronous positioning updates after a newer positioning effect has started.
Merged refs preserve React 19 callback ref cleanup functions while still detaching refs that do not return a cleanup.
Nested value updates treat path segments such as
-1,Infinity, andNaNas object keys rather than array indexes.Hides content with
clip-path: inset(50%)instead of the deprecatedclipproperty; the technique also applies to other visually hidden elements.Components and shared helpers no longer throw when event.target or event.relatedTarget is a non-element EventTarget.
Runtime NODE_ENV checks in published package output now work correctly, including test-only behavior and development warnings.
Menu now respects autoFocusOnShow when it is false or a callback returns false, while still allowing arrow keys to move focus into an already-open menu.
Portals move to document.fullscreenElement while fullscreen is active and return to document.body when fullscreen is exited.
Components now drop their internal aria-labelledby when aria-label is passed.
In Safari, buttons, checkboxes, and radio buttons receive an explicit tabIndex so the browser focuses them natively, replacing manual focusing in a mousedown handler.
Generic React wrappers now type-check for controlled and uncontrolled checkbox groups without non-null assertions on values such as defaultValue.
The input's horizontal scroll position is preserved when results change and virtual focus moves focus away from and back to the input.
Pressing Escape now closes ComboboxPopover when it starts open and the Combobox input is auto-focused.
Controlled reset states are now reflected correctly by the menu item and MenuItemCheck.
Fixed an error when trying to reach focusable elements within iframes.
Fixed issues with React 19 types.
Fixed RefObject types for React 19.