# Changelog

URL: https://ark-ui.com/docs/overview/changelog
LLM: https://ark-ui.com/llms.txt/overview/changelog

All notable changes will be documented in this file.

---

# @ark-ui/react

## [5.38.2] - 2026-08-17

### Fixed

- Fix `Fieldset.Root` re-rendering whenever its subtree mutated, even if helper and error text were unchanged. A nested
  `Field.Textarea` with `defaultValue` could turn that into a loop that froze the tab.

- Fix Next.js 15 production builds failing because React's optional `Activity` export was imported statically. Ark now
  resolves `Activity` at runtime and falls back to `display-none` when the active React build does not expose it.

- - **Date Picker**
    - Fix `translations` requiring every message. It's now `Partial`, so you can override one message and let the rest
      fall back to the defaults.
    - Fix the view trigger's `aria-label` naming the wrong view. In day view it announced "Switch to year view" while
      the trigger actually switches to month view. The trigger also disables itself once there's no further view to
      switch to.
    - Fix dates between a range's start and end announcing the generic "Choose" label. They now announce "In range".
  - **Escape Dismissal**: Fix `Escape` being ignored right after an overlay opens. Handlers registered a frame late, so
    the overlay was painted and focus-trapped before it could listen. Under CPU load that gap grew well past one frame
    and swallowed the keypress. They now register as soon as the layer mounts.
    > Affects Dialog, Drawer, Menu, Popover, and anything else that closes on `Escape`.
  - **Floating Panel**
    - Fix closing a panel leaving it on the stack, so the next panel now becomes topmost.
    - Fix stack order not applying to the positioner, so focusing a panel raises it above its siblings.
  - **Focus Visible**: Fix clicking a label adding `data-focus-visible` to the control. Activating the label briefly
    moved focus to an overlay container, which was read as virtual focus.
    > Affects Checkbox, Radio Group, and Switch.
  - **Form Submission**: Fix trigger and close trigger buttons submitting an ancestor form on click. They carried no
    `type`, so they defaulted to `type="submit"`.
    > Affects Drawer, Navigation Menu, Steps, and Tour.
  - **Hover Highlight**: Fix keyboard navigation losing or moving the highlighted item while the pointer rests over
    scrollable content. Scrolling the item into view moved the content under the cursor, and the resulting
    `pointerleave` (or `pointermove` in Safari) counted as a real hover.
    > Affects Cascade Select, Combobox, Listbox, Menu, and Select.
  - **Image Cropper**: Fix `fixedCropArea` disabling every keyboard interaction on the crop selection, including the `+`
    and `-` zoom shortcuts that still apply in fixed mode. The selection is now always focusable, and arrow keys pan the
    image since there's nothing to move or resize.
  - **QR Code**: Fix `getDataUrl()` and the download trigger dropping the overlay. The export contained only the QR
    matrix, so a logo or badge placed over the code went missing.
  - **Splitter**: Fix the resize trigger matching `:focus-visible` after a pointer drag. It still takes focus, so
    keyboard resizing keeps working, but no longer shows the focus ring.
  - **Tags Input**: Fix an XSS vector in the hidden element that measures input width. It set the tag value with
    `innerHTML`, so a value containing markup was parsed and could execute. It now uses `textContent`.

## [5.38.1] - 2026-08-07

### Fixed

- Fix `composeRefs`/`useComposedRefs` not resetting plain callback refs and object refs to `null` on detach when
  composed alongside a React 19 ref that returns a cleanup function.

## [5.38.0] - 2026-08-01

### Added

- Added `hideMode` (`'display-none' | 'activity'`) for how kept-mounted content is hidden when closed. Covers
  presence-based overlays and Collapsible (including Accordion and TreeView).
  - `'display-none'` (default): HTML `hidden`. Effects stay alive.
  - `'activity'`: React 19 [`Activity`](https://react.dev/reference/react/Activity). Effects pause. Applies while
    content stays mounted:

  ```jsx
  // applies from the start
  <Dialog.Root hideMode="activity" />
  // applies after the first open (lazyMount only delays the first mount)
  <Dialog.Root lazyMount hideMode="activity" />
  <Collapsible.Root hideMode="activity" />
  <Accordion.Root hideMode="activity" />
  ```

  Does not apply when content is unmounted:

  ```jsx
  // unmountOnExit removes the tree on close, so hideMode never runs
  <Dialog.Root lazyMount unmountOnExit hideMode="activity" />
  ```

- - **Number Input**: Add `largeStep` and `smallStep` props for configurable keyboard stepping. Hold `Shift` for
    `largeStep` (defaults to `10 * step`), `Alt` for `smallStep` (defaults to `step / 10`). The defaults match the
    previous behavior.
    ```jsx
    <NumberInput.Root largeStep={20} smallStep={0.5} />
    ```
  - **Slider**: Add `largeStep` prop, applied on `Shift` or `PageUp`/`PageDown` (defaults to `10 * step`). The default
    matches the previous behavior.

- - **Autofocus Control**: Add `data-autofocus` and `data-no-autofocus` to decide what gets focus when an overlay opens.
    Mark chrome like the close button with `data-no-autofocus` to skip it, or mark the real target with
    `data-autofocus`.
    ```jsx
    <Dialog.Content>
      <Dialog.CloseTrigger data-no-autofocus>Close</Dialog.CloseTrigger>
      <input data-autofocus />
      <button>Save</button>
    </Dialog.Content>
    ```
    Focus goes to `initialFocusEl`, then `[data-autofocus]`, then the first tabbable element without
    `[data-no-autofocus]`, then the content root.
    > Supported in Dialog and Drawer.
  - **Focus Trap**: Add `persistentElements` to treat portalled content as part of the trap when it isn't reachable via
    `aria-controls`/`aria-expanded`. Pass getters so the elements can be resolved lazily.
    ```jsx
    <FocusTrap persistentElements={[() => document.getElementById('toast-region')]} />
    ```
  - **Image Cropper**: `getCropData()` now returns the exact `corners` and `outputSize` of the crop in natural-image
    pixels, so you can hand the region straight to a server-side cropper.
  - **Image Cropper**: Add `maxSize` to `getCroppedImage()` to cap the output dimensions. The crop keeps its aspect
    ratio and scales down to fit.
    ```jsx
    const blob = await imageCropper.getCroppedImage({ maxSize: { width: 512, height: 512 } })
    ```

### Fixed

- Fixed composed refs to keep stable callback refs attached across re-renders.

- Exposed the toast content generic on `createToaster` so `CreateToasterReturn<T>` can type custom toast data.

- Fixed Steps `RootProvider` rendering children twice via both `mergedProps` and explicit `{props.children}`.

- - **Date Input**
    - Type dates using your locale's native numerals (Arabic-Indic `٠-٩`, Devanagari `०-९`), not just ASCII digits.
    - Fix timezone-naive values (`CalendarDate`/`CalendarDateTime`) shifting by your local UTC offset when you pass a
      custom `formatter` without a `timeZone`. A wall-clock value now round-trips unchanged.
  - **Date Picker**
    - Type dates using your locale's native numerals, not just ASCII digits.
    - Reorder dates on blur in range selection, matching the other selection paths.
    - Fix the day view briefly flashing when you close the picker from the month or year view.
    - Fix `visibleRangeText` returning a stale value when multiple pickers share a visible range. This was also causing
      SSR hydration mismatches.
  - **Menu**: Fix the context menu flashing at the top-left before positioning. Long-press (touch) context menus no
    longer open stuck at `(0,0)`.
  - **Number Input**
    - Fix `api.setValue` throwing when you pass a number and `formatOptions` is set.
    - Fix `Cmd`/`Ctrl` + arrow keys producing values off the `step` grid.
  - **Slider**: Fix `Cmd`/`Ctrl` + arrow keys producing values off the `step` grid.
  - **Tags Input**: Fix native form submit so `FormData` reflects the current tags. The hidden input used to keep its
    initial value after you added, removed, or cleared tags.
  - **Toast**: Fix a height flicker when expanding the stack in overlap mode. Heights are now measured without the
    `scale` transform.

- - **Color Picker**: Fix the channel input committing a partial value when you press `Enter` to confirm an IME
    composition.
  - **Date Input**
    - Fix segment text lagging behind while you type over an already committed date.
    - Fix in-progress edits being dropped while focus catches up after auto-advance. Fast typing and
      `ArrowUp`/`ArrowDown`/`Home`/`End` now land on the segment you're actually editing.
  - **Date Picker**
    - Fix disabled and read-only pickers still reacting to cell clicks, the clear trigger, and presets. Read-only
      pickers keep roving-focus navigation; disabled pickers drop out of the tab order.
    - Fix `minView`, `maxView`, and `defaultView` being ignored when resolving the initial view, which was hardcoded to
      day through year.
    - Fix `defaultOpen` winning over `open`, so a controlled picker could open against its own prop.
    - Fix `maxSelectedDates` not being enforced on month and year cells in `multiple` selection mode.
    - Fix keyboard range selection drifting from pointer behavior. Picking a third date restarts the range, and the
      hover preview updates for `Enter`, `Home`, `End`, and `PageUp`/`PageDown`.
    - Fix reopening the calendar with only a start date restarting the range instead of resuming it.
  - **Drawer**: Fix the backdrop flickering on a controlled close when the `open` setter is async.
  - **Field**: Fix `Field.Textarea` with `autoresize` dispatching a synthetic `input` event when you set `value`
    programmatically, which fed the value back into your framework and broke controlled state.
  - **Focus Return**: Fix three focus-trap issues you'd hit with overlays.
    - Closing an overlay no longer steals focus back from an element your app focused in the meantime, like a second
      dialog opened right after closing the first.
    - Closing a nested overlay, such as a popover inside a dialog, no longer throws when the outer container has no
      connected focusable element at that moment.
    - The focus ring now shows on the returned-to element after you close with `Escape`.
    > Affects Dialog, Drawer, Popover, and anything else that traps focus.
  - **Image Cropper**: Fix `getCroppedImage()` and `getCropData()` returning a different region from the one you see
    after rotating or flipping the image.
  - **Marquee**: Fix scroll speed depending on content width. The duration now comes from the content size and the
    actual translation distance, so `speed` matches real pixel speed even when the content is narrower than the
    viewport.
  - **Popover**: Fix tabbing out of portalled content looping back into the content when the trigger was the last
    tabbable element on the page. Focus now moves to the next tabbable element after the trigger.
  - **Scroll Lock**: Fix the scroll lock targeting `<body>` on layouts where `<html>` is the real scroll container,
    which meant nothing was locked while an overlay was open.
  - **Signature Pad**: Fix controlled `paths` drifting out of sync because the in-progress stroke was appended to
    `paths`. It now stays in `onDraw.currentPath` until the stroke ends.
  - **Splitter**
    - Fix collapsed panels sizing to `minSize` instead of `collapsedSize`.
    - Fix keyboard resizing breaking when a resize trigger got focus while hovered.
  - **Tour**
    - Fix dismissing a tour from a step's `effect` skipping cleanup, which could miss firing the `completed` status.
    - Fix a tooltip step's position resetting unexpectedly when the tour closed.
    - Fix a step action with `action: "skip"` doing nothing when clicked.
  - **Solid**: Fix a `value` of `null` being read as uncontrolled, so controlled components fell back to internal state.
  - **Solid, Svelte**: Fix machine exit actions running when a component was disposed before the machine started.
  - **Vue, Svelte**: Fix `defaultValue` being resolved before `value`, unlike React and Solid.

## [5.37.2] - 2026-06-08

### Fixed

- Fix declaration file output paths so published package export maps resolve to existing types.

## [5.37.1] - 2026-06-06

### Fixed

- - **Date Input**: Fix segment placeholders for locales with explicit script subtags.
  - **Drawer**: Fix flickering when a controlled drawer is swiped or backdrop-closed while the `open` setter is async
    (e.g. the History API or a delayed state update).
  - **Image Cropper**: Fix `getCroppedImage` and `getCropData` returning the wrong region when the image is shown at a
    size different from its natural resolution (e.g. `width` / `height` of `100%`).
  - **Pin Input**: Fix `data-filled` being set on every input on first render.
  - **Signature Pad**: Fix the `dir` prop being accepted but never forwarded to the DOM.

## [5.37.0] - 2026-05-26

### Added

- **Floating Components**: Add `data-side` to placement-aware parts so you can style them based on the current placement
  (`top`, `bottom`, `left`, `right`).

  > Affects Color Picker, Combobox, Date Picker, Hover Card, Menu, Popover, Select, Tooltip, and Tour.

- **Date Input**: Add `hideTimeZone` prop. When the value is a `ZonedDateTime`, the `timeZoneName` segment now renders
  automatically — set `hideTimeZone` to hide it. Arrow navigation and auto-advance after typing now reach read-only
  focusable segments too.

- **Splitter**
  - Accept CSS units (`px`, `em`, `rem`, `vh`, `vw`) for `defaultSize`, `minSize`, and `maxSize` in addition to
    percentages.

    ```jsx
    <Splitter.Root
      panels={[
        { id: 'nav', minSize: '240px', maxSize: '480px' },
        { id: 'main', minSize: 30 },
      ]}
      defaultSize={['240px', '60vw']}
    />
    ```

  - Add `resizeBehavior` per panel. Set to `"preserve-pixel-size"` to keep a panel's pixel size constant when the parent
    splitter group resizes.

  - Allow non-panel children (toolbars, rails, status bars) inside the splitter root. Use partial trigger ids
    (`"left:"`, `":right"`) to bind handles around the fixed element.

### Fixed

- **Accordion**: Remove redundant `aria-disabled` from item triggers.

- **Color Picker**: Fire `onValueChangeEnd` when you pick a color with the EyeDropper API — matches the behavior when
  ending a drag on the area or channel sliders.

- **Combobox**: Stop `Enter` from submitting the form when an item is highlighted, or when the typed value will be
  rejected by `allowCustomValue: false`.

- **Date Input**
  - Preserve entered segments when applying min/max. Values clamp segment-by-segment on blur, so `06/15/1999` with min
    `2000-01-01` becomes `06/15/2000` instead of snapping to `01/01/2000`.

  - Fix range mode keyboard navigation so `ArrowRight` moves from the last segment of the start date to the first
    segment of the end date.

  - Fix time-only formatters (no `year` segment) never firing `onValueChange`.

  - Fix `setSegmentValue` reading stale display values.

  - Fix `dayPeriod` (AM/PM) arrow up/down not updating the visible segment when `hourCycle` changes at runtime.

  - Fix typing "A" / "P" on the `dayPeriod` segment not updating the visible AM/PM.

- **Date Picker**
  - Fix clearing the value not resetting `activeIndex` and `hoveredValue` in range mode when input parts are not
    rendered.

  - Fix date input not being writable in locales with multi-character separators (e.g. `cs-CZ`, `sk-SK`, `hu-HU`,
    `ko-KR`).

  - Fix Firefox issue where the native month/year `<select>` was not interactive when the picker is inside a modal
    dialog.

  - Fix range selection with `outsideDaySelectable`: hovering outside-month days no longer changes the visible month;
    hover preview for the end date still updates.

- **Dialog, Drawer, Hover Card, Menu, Popover, Tooltip**: Fix custom trigger elements (via `ids.trigger`) being ignored
  when shared across components — e.g. wrapping a `Popover.Trigger` in a `Tooltip` with the same id no longer breaks
  positioning. Also fix trigger lookups in shadow root.

- **Dialog, Drawer, Popover**: Fix dismissable layers losing their `pointer-events` in Svelte and Vue, where a spread
  update could rewrite the whole `style` attribute and wipe the value.

- **Drawer**
  - Fix controlled drawers snapping back open before the close animation when dismissed by swipe.

  - Fix the indent and indent background snapping into place after the close animation instead of transitioning in sync.

  - Fix `--drawer-swipe-progress` jumping straight to `1` at the start of a dismiss swipe — it now moves smoothly from
    `0` (at rest) to `1` (fully dismissed).

  - Fix the drawer freezing mid-drag on release when its content mounts lazily, which left snap points unmeasured.

- **React 19 Strict Mode**: Fix dialog, drawer, and popover leaving `<body>` uninteractive (`data-scroll-lock`,
  `data-inert`, `overflow: hidden`, `pointer-events: none`) after closing.

- **Number Input**: Fix inconsistent blur behavior when the input is cleared and `min` is greater than `0`.

- **Splitter**
  - Fix clicking a resize trigger not moving focus to it, which prevented arrow keys from resizing the splitter until it
    was tab-focused (notably on Safari).

  - Fix `data-focus` being applied on hover — it now only sets when the trigger is actually focused.

- **Tabs**: Observe the tab list with `ResizeObserver` so the indicator updates when the list resizes without individual
  tab triggers changing size (e.g. responsive grid reflow).

- **Floating Panel**: Re-export additional types (`ResizeTriggerAxis`, `Stage`, `ElementIds`, `IntlTranslations`,
  `AnchorPositionDetails`, `Point`, `Size`) and the `resizeTriggerAxes` constant from `@zag-js/floating-panel`.

## [5.36.2] - 2026-04-22

### Fixed

- **Field**: Export `FieldItem` component from the top-level package. The component was previously only accessible via
  the `Field.Item` namespace.

- Fix React Server Components build failure caused by a stray `"use client"` directive on the shared
  `_virtual/_rolldown/runtime.js` helper emitted by vite 8's rolldown backend.

- **DownloadTrigger**: Extract the download logic into a `useDownload` hook. The `DownloadTrigger` component now simply
  consumes this hook, making the browser-download behavior reusable outside of the trigger component.

## [5.36.1] - 2026-04-14

### Fixed

- **Popover**: Add `finalFocusEl` and `restoreFocus` props to control focus behavior when the popover closes.
  `finalFocusEl` lets you specify an element to receive focus instead of the trigger, and `restoreFocus` (default
  `true`) controls whether focus returns to the trigger at all.

```jsx
<Popover.Root finalFocusEl={() => myInputRef} restoreFocus={false}>
  ...
</Popover.Root>
```

- **Color Picker**: Fix color value to respect the specified `format` when setting values via props or `setValue`.
  Previously, the internal color object could retain a mismatched format (e.g., RGB when `format` is `hsla`), causing
  inconsistent `value` objects in `onValueChange` callbacks.

- **Date Input**: Fix min/max constraints resetting other segments mid-keystroke. Validation now defers until the
  segment is fully typed or on blur.

- **Date Picker**: Fix `onValueChange` not firing when only time segments change in `CalendarDateTime` or
  `ZonedDateTime` values.

- **Navigation Menu**: Remove aggressive and redundant default `aria-label`.

## [5.36.0] - 2026-04-10

### Added

- Add new `DateInput` component for typing dates with keyboard input.

```jsx
<DateInput.Root>
  <DateInput.Label />
  <DateInput.Control>
    <DateInput.SegmentGroup>
      <DateInput.Segment />
    </DateInput.SegmentGroup>
  </DateInput.Control>
  <DateInput.HiddenInput />
</DateInput.Root>
```

- **Multiple Trigger Support**: No more duplicating a Dialog for every button in a list — render one instance and share
  it across as many triggers as you need. Each trigger gets a `value`, and the component repositions automatically when
  switching between them.

  ```jsx
  <Dialog.Root>
    <Dialog.Trigger value="user-1">Edit Alice</Dialog.Trigger>
    <Dialog.Trigger value="user-2">Edit Bob</Dialog.Trigger>
    {/* one dialog, reused for both */}
  </Dialog.Root>
  ```

  > Supported in Dialog, Drawer, Hover Card, Menu, Popover, and Tooltip.

- **Splitter**: Nest splitters to build grid-like layouts. When a horizontal and vertical splitter meet at an
  intersection, you can drag both directions at once. Use `createRegistry()` to connect the splitter instances.

  ```jsx
  const registry = Splitter.createRegistry()

  <Splitter.Root orientation="horizontal" registry={registry}>
    <Splitter.Panel>
      <Splitter.Root orientation="vertical" registry={registry}>
        ...
      </Splitter.Root>
    </Splitter.Panel>
  </Splitter.Root>
  ```

- **Tags Input**: Add `sanitizeValue` prop to clean up tag values before they're added — trim whitespace, lowercase,
  strip special characters, whatever you need. Defaults to `(v) => v.trim()`.

  ```jsx
  <TagsInput.Root sanitizeValue={(v) => v.trim().toLowerCase()} />
  ```

- **Toast**: Add priority-based queuing. When you've hit the max visible toasts, incoming ones are queued and sorted so
  the most important ones show first.

- **Floating Panel**: Add `initialFocusEl`, `finalFocusEl`, and `restoreFocus` props to control which element gets focus
  when the panel opens or closes.

### Fixed

- **Date Input**: Fix crash in non-React frameworks (Vue, Solid, Svelte) where `event.nativeEvent.isComposing` is
  `undefined`. The composing check now uses a framework-agnostic utility that works across all adapters.

- **Dialog / Drawer**: Avoid setting inline `pointer-events` when modal, letting the dismissable layer manage it
  instead.

- **File Upload**: Automatically reject duplicate files with `FILE_EXISTS` error. Previously, uploading the same file
  twice was silently accepted and deleting one duplicate removed all of them.

- **Splitter**: Fix `onResizeStart` and `onResizeEnd` callbacks to fire for programmatic resizes.

- **Tags Input**: Set `enterKeyHint` to `"done"` on the input element so mobile virtual keyboards show a "Done" button
  that triggers tag addition.

- **Toast**: Restore `role="region"` on the toast group element. The role was previously removed to reduce screen reader
  landmark noise, but this caused an axe `aria-prohibited-attr` violation since `aria-label` is not permitted on a `div`
  without a valid role.

- **Tour**: Fix step navigation events (`next`, `prev`, `setStep`) firing when the tour is inactive, bypassing the
  `start` flow. Fix popper styles not being cleaned up when transitioning from a tooltip step to a dialog step.

- **Tree View**: Add `data-checked` and `data-indeterminate` attributes to item and branch control elements for styling
  based on checked state.

- **Accordion**: Fix missing `data-focus` attribute on `getItemTriggerProps`.

- **Combobox**: Fix VoiceOver not announcing combobox options when navigating with arrow keys. Safari/VoiceOver ignores
  `aria-activedescendant` changes on combobox inputs, so a live region is now used to announce the highlighted item on
  Apple devices.

- **Menu**: Fix issue where quick diagonal pointer movement toward an open submenu could flash the highlight across
  sibling items you skim past.

## [5.35.0] - 2026-03-26

### Added

- **Date Picker**: Improved range picker mode with new data attributes and state properties.
  - Added missing range data attributes (`data-range-start`, `data-range-end`, `data-in-hover-range`,
    `data-hover-range-start`, `data-hover-range-end`) to month and year cell triggers.
  - `TableCellState` now includes `firstInRange`, `lastInRange`, `inHoveredRange`, `firstInHoveredRange`,
    `lastInHoveredRange`, and `outsideRange`.
  - Range boundary dates now announce "Starting range from {date}" and "Range ending at {date}" for better screen reader
    context.
  - Fixed inverted year cell `selectable` state that caused years outside the visible decade or min/max range to appear
    selectable.
  - **Breaking:** `DayTableCellState.formattedDate` removed — use `valueText` instead (inherited from `TableCellState`).

- **Drawer**: Added new anatomy parts and improved swipe gestures.
  - Added `description` anatomy part with `aria-describedby` support on the content element.
  - Added `SwipeArea` part for swipe-to-open gestures from screen edges.
  - Require intentional swipe movement before showing the drawer (no flash on pointer down).
  - Smooth settle animation from release point to fully open position.
  - Added cross-axis scroll preservation to prevent drawer drag when scrolling horizontally.
  - Added initial focus management for non-modal mode.
  - Set `pointer-events: none` on positioner in non-modal mode so the page stays interactive.
  - Fixed swipe-to-dismiss in controlled mode (`open: true` without `onOpenChange` now blocks dismiss).

- **Field**: Added `Field.Item` component and `target` prop on `Field.Root` for multi-control fields (e.g., currency
  select + amount input). Use `Field.Item` with a `value` to scope controls, and `target` to specify which item the
  label should focus when clicked.

- **Interaction**: Added `useInteractionModality` and `useFocusVisible` hooks for tracking user input method (keyboard,
  pointer, virtual) and conditionally showing focus rings.

- **Listbox**: Added `keyboardPriority` to input props to control whether key handling prioritizes text editing or list
  navigation for `Home`/`End` and horizontal arrows in grid collections. Added `highlightFirst`, `highlightLast`,
  `highlightNext`, and `highlightPrevious` to the API for programmatic highlight navigation.

- **Pin Input**: Overhauled deletion, focus management, and added new props.
  - Delete and Backspace now splice values left instead of leaving empty gaps. Deleting "2" from `[1, 2, 3]` yields
    `[1, 3, ""]` — not `[1, "", 3]`.
  - Smarter focus management: Backspace always moves back, click and ArrowRight are clamped to the insertion point,
    same-key skip advances focus, and roving tabIndex treats the entire pin input as a single tab stop.
  - Added Home/End to jump to first slot or last filled slot.
  - Added `enterKeyHint` showing "next" on intermediate slots and "done" on the last.
  - Added `autoSubmit` prop to automatically submit the owning form when all inputs are filled.
  - Added `sanitizeValue` prop to sanitize pasted values before validation (e.g. strip dashes from "1-2-3").

- **Tags Input**: Added `allowDuplicates` prop to allow duplicate tags.

- **Clipboard, Navigation Menu, Popover, Select, Timer, Tree View**: Added `translations` prop for localizing hardcoded
  accessibility labels.

### Fixed

- **Carousel**: Fixed controlled carousel inside dialog jumping or skipping pages. Fixed navigation inside
  CSS-transformed containers (e.g., dialogs with open/close animations). Fixed scroll position drifting when container
  layout shifts (e.g., scrollbar removal).

- **Color Picker**: Fixed vertical slider orientation not preserved on pointer updates.

- **Date Input**: Improved focus management.

- **Dialog**: Improved non-modal mode behavior.
  - Set `pointer-events: none` on positioner in non-modal mode so the page stays interactive.
  - Added initial focus management for non-modal mode (mirrors popover behavior).
  - Fixed `aria-modal` to reflect actual `modal` prop value instead of hardcoded `true`.

- **Floating Panel**: Fixed `open` taking precedence over `defaultOpen` during initialization. Fixed `setPosition` and
  `setSize` to work independently of drag/resize state. Fixed maximize/minimize restore reverting to `(0, 0)` in
  controlled mode. Fixed `Maximum update depth exceeded` when content uses `ResizeObserver` (React). Fixed Escape during
  drag/resize to cancel and revert to original position/size.

- **Focus Trap**: Fixed edge cases in focus trapping.
  - Fixed focus trapping when the content has a single effective tab stop, such as a native radio group.
  - Handle disconnected `initialFocus` nodes more safely.

- **Interact Outside**: Fixed Safari-specific interaction issue.
  - Fixed issue where nested popovers and select within popovers didn't toggle correctly in Safari due to `focusin`
    events racing with pointer interactions.

- **Menu**: Fixed trigger to keep `aria-expanded="false"` when closed.

- **Pin Input**: Fixed crash when typing the same character in a completed pin input.

- **Radio Group, Tabs**: Fixed indicator only animating on value change, not on initial render or resize.

- **Splitter**: Fixed shadow root compatibility.
  - Fixed global cursor styles when splitter is used in a shadow root.

## [5.34.1] - 2026-03-03

### Fixed

- **Carousel**:
  - Fixed issue where carousel inside a Portal (e.g., Dialog) computes incorrect page count due to incomplete DOM layout
    at mount time
  - Keep page and indicators in sync after drag release and scroll settling
  - Handle rapid mixed interactions (drag, wheel, buttons, indicators) more consistently
  - Keep page state valid when `slidesPerPage`, `slidesPerMove`, direction, or orientation change
  - Make `slidesPerMove` progression more predictable
- **Combobox, Listbox, Select**: Improved controlled-mode synchronization and callback/item resolution behavior across
  filtered collections

### Changed

- **Format**: `Format.Time` now accepts `amLabel` and `pmLabel` as separate props instead of the previous `amPmLabels`
  object

## [5.34.0] - 2026-02-27

### Added

- **Format**: Added `Format.Time` for formatting time values and examples for basic, date input, seconds, custom AM/PM
  labels, and locale

### Fixed

- **Build**: Fixed CJS build issues in downstream Zag.js packages

## [5.33.0] - 2026-02-26

### Added

- **Date Picker**: Added non-Gregorian calendar support via `createCalendar` prop (Persian, Buddhist, Islamic, Hebrew,
  and other calendar systems)

  ```jsx
  import { PersianCalendar } from '@internationalized/date'

  function createCalendar(identifier) {
    switch (identifier) {
      case 'persian':
        return new PersianCalendar()
      default:
        throw new Error(`Unsupported calendar: ${identifier}`)
    }
  }

  ;<DatePicker.Root locale="fa-IR" createCalendar={createCalendar}>
    {/* ... */}
  </DatePicker.Root>
  ```

- **Date Picker**: Added `data-type` attribute to weekend table header and cell

### Fixed

- **Combobox**: Fixed `onValueChange` returning empty `items` array when using controlled value
- **Popover**: Fixed nested popover z-index layering
- **Toast**: Fixed types to ensure `parent`/`index` are exposed as props and `expand`/`collapse` are exposed on the
  store
- **Radio Group, Listbox, Progress, Segment Group**: Fixed group labels rendering orphan label elements; now render as
  `span` per W3C ARIA pattern

## [5.32.0] - 2026-02-21

### Added

- **Locale**: Added `useDateFormatter` hook for localized date formatting using `@internationalized/date`
- **Swap**: Added new `Swap` component for toggling between two visual states with CSS animations using dual presence
  instances
- **Checkbox**: Added `maxSelectedValues` prop to `CheckboxGroup` to limit the number of selected values
- **Drawer**: Replaced `BottomSheet` with new `Drawer` component supporting multi-directional swipe via `swipeDirection`
  prop (`up`, `down`, `left`, `right`), a new `Positioner` part, and `snapToSequentialPoints` option
- **Date Picker**:
  - Added `focus` option to `api.clearValue({ focus?: boolean })`
  - Added `api.setTime(time, index?)` for date-time picker support
  - Added `maxSelectedDates` prop to limit selected dates in `multiple` selection mode
  - Added `api.isMaxSelected` to check if maximum number of dates has been selected
  - Added `openOnClick` prop to open the calendar when clicking the input field
  - Added `showWeekNumbers` support to display ISO 8601 week number column in the day view
- **Popover**: Added `sizeMiddleware` positioning option to optionally disable the size middleware
- **Select**: Added `autoComplete` prop for browser autofill hints

### Fixed

- **Combobox**:
  - Fixed `aria-selected` being set on highlighted items instead of selected items
  - Fixed `selectedItems` getting out of sync with `value` in controlled mode
  - Fixed item disabled state not accounting for root-level `disabled` prop
- **Date Picker**:
  - Fixed `api.selectToday()` sending incorrect value format
  - Preserve time/timezone when selecting new dates (`CalendarDateTime` and `ZonedDateTime`)
  - Improved focus management in trigger-only mode
- **Dialog**: Fixed non-modal dialog closing on outside click when `modal` is `false`
- **Listbox**: Fixed DOM IDs
- **Number Input**: Fixed `invalid` prop being ignored when value is out of range
- **Popover**: Improved performance by reducing style recalculations when scrolling
- **Select**: Fixed autofill not updating value when hidden select value changes

## [5.31.0] - 2026-02-04

### Added

- **Date Picker**: Added `ValueText` component for displaying selected date value(s) with placeholder support and render
  prop for custom formatting
- **Scroll Area**: Added overflow CSS variables (`--scroll-area-overflow-{x,y}-{start,end}`) for scroll fade effects
- **Slider**: Added `thumbCollisionBehavior` prop (`none`, `push`, `swap`)
- **Steps**: Added `isStepValid`, `isStepSkippable`, and `onStepInvalid` for validation support
- **Tags Input**: Added `placeholder` prop (shown only when no tags exist)
- **Tooltip**: Added `data-instant` attribute for instant animations

### Fixed

- **Auto Resize**: Fixed change event not emitted after clearing controlled textarea
- **Date Picker**: Fixed `visibleRangeText` to show correct format based on current view (year/month/day)
- **Dismissable**: Fixed issue where closing a nested dialog/popover would incorrectly close its parent layers
- **Menu**: Fixed glitchy submenu behavior when hovering between trigger items quickly
- **Checkbox**: Fixed individual checkbox props being overridden by `CheckboxGroup`
- **Collection, Tree View**: Fixed initial focus when first node/branch is disabled
- **Color Picker**: Fixed color not updating when selecting black shades in controlled mode
- **Floating Panel**: Fixed double-click on minimized title bar incorrectly maximizing
- **Image Cropper**: Fixed `reset()` destroying cropper, prop changes not updating instantly, and panning bounds
- **Number Input**: Fixed cursor positioning after clicking label or scrubbing
- **Pagination**: Fixed next trigger not disabled when `count` is `0`
- **Slider**: Fixed thumb drag from edge in `thumbAlignment="contain"` mode
- **Switch**: Fixed `api.toggleChecked()` not working
- **Toast**: Fixed toasts created before state machine connects not showing
- **Tour**: Fixed janky scroll between steps

## [5.30.0] - 2025-12-10

### Added

- **Date Picker**: Added `required` and `invalid` props
- **Number Input**: Added `onValueCommit` callback that fires when the input loses focus or Enter is pressed
- **Pagination**:
  - Added `FirstTrigger` and `LastTrigger` components for navigating to first/last page
  - Added `boundaryCount` parameter for controlling boundary pages (start/end)
  - Implemented balanced pagination algorithm for consistent UI with max 7 elements
- **Radio Group**: Added `invalid` and `required` props with corresponding `data-*` and `aria-*` attributes
- **Tree View**: Added `scrollToIndexFn` prop to enable keyboard navigation in virtualized trees

### Fixed

- **Accordion, Menu**: Fixed issue where querying elements by `aria-controls` attribute could fail when lazy mounting
  the content
- **Color Picker**: Added `role="dialog"` to content and `aria-haspopup="dialog"` to trigger when not inline for better
  accessibility
- **Date Picker**: Fixed issue where date picker input does not update format when locale changes
- **Floating Panel**:
  - Fixed `dir` prop now properly delegated to all panel parts
  - Fixed double-click behavior improvements and to check `event.defaultPrevented` for custom behavior
- **Listbox**:
  - Fixed issue in React where filtering items with an input would throw a
    `flushSync was called from inside a lifecycle method` warning
  - Fixed issue where `data-highlighted` wasn't applied to the first item when using `autoHighlight` with input
    filtering
- **Number Input**:
  - Fixed improved controlled usage sync
  - Fixed issue where input element doesn't sync when `formatOptions` changes dynamically
  - Ensured cursor position is preserved when `Enter` key is pressed and formatting is triggered
  - Fixed cursor jumping to start when value is changed externally via props while user is typing
- **Pagination**: Fixed ellipsis showing when only 1 page gap
- **Rating Group**: Fixed issue where rating group becomes unfocusable via keyboard when value is 0
- **Tooltip**: Fixed tooltip not showing when scrolling with pointer over trigger

### Changed

- **Tree View**: `getVisibleNodes()` now returns `{ node, indexPath }[]` instead of `node[]`

## [5.29.1] - 2025-11-22

### Fixed

- **Fieldset**: Fixed `aria-describedby` resolution to correctly reference helper text and error text IDs
- **Floating Panel**:
  - Fixed resize trigger issue with `n` axis by explicitly setting `top: 0`
  - Fixed `draggable` and `resizable` options not being respected when set to `false`
- **Presence**: Fixed regression where UNMOUNT transition might not be called consistently

## [5.29.0] - 2025-11-20

### Added

- **Carousel, Color Picker, Combobox, Date Picker, Select**: Added `value` to `OpenChangeDetails` for better context
  when handling open state changes
- **Carousel**: Added support for `autoSize` prop to allow variable width/height slide items
- **Splitter**:
  - Added `Splitter.ResizeTriggerIndicator` to render an indicator when resizing
  - Exported `getLayout` and `getSplitterLayout` functions for calculating splitter panel layouts
- **Toast**: Exposed viewport offset as CSS variables on the toast group element

### Fixed

- **Carousel**:
  - Fixed dragging behavior that stops working after switching browser tabs or scrolling the page
  - Fixed dragging not working after scrolling with mouse wheel when `allowMouseDrag` is enabled
- **Combobox**: Fixed `onHighlightChange` not being invoked when collection is filtered to empty
- **Date Picker**: Fixed issue where the range date picker crashes when typing the end date first and blurring the input
  field multiple times
- **File Upload**: Fixed issue where clicking on non-interactive children inside the dropzone doesn't open the file
  picker
- **Presence**: Fixed a bug where elements get stuck in unmountSuspended state during rapid state updates
- **Radio Group**:
  - Fixed inconsistent application of `data-focus-visible` and `data-focus` attributes
- **Splitter**: Fixed disabled splitter showing resize cursor and allowing dragging
- **Tabs**:
  - Fixed tabs indicator position not updating when inactive tabs change size
- **Tags Input**: Fixed issue where item delete trigger doesn't have `data-*` attached

## [5.28.0] - 2025-11-14

### Added

- **General**: Exported `InteractOutsideEvent`, `FocusOutsideEvent`, and `PointerDownOutsideEvent` types for better type
  safety
- **Carousel**:
  - Added `Carousel.AutoplayIndicator` component for conditionally rendering content based on autoplay state
  - Added `Carousel.ProgressText` component for displaying current page progress (e.g., "1 / 5")
- **Toast**: Exported `ToastOptions` and `ToastStoreProps` types for better type safety

### Changed

- **useListCollection**: Updated `initialItems` to accept `readonly` arrays for better compatibility with immutable data
  patterns.

### Fixed

- **Combobox**:
  - Fixed focus stealing in controlled open mode
  - Removed problematic `aria-hidden` behavior to allow interaction with other page elements

## [5.27.1] - 2025-11-02

### Fixed

- **Dialog, Popover**: Improved shadow DOM support for interact outside and focus trap detection
- **Marquee**: Fixed Firefox flicker and added GPU acceleration
- **Dialog**: Fixed layout shift issue when using `scrollbar-gutter: stable` in CSS
- **Slider**: Fixed `onValueChangeEnd` callback not triggering for programmatic value changes

## [5.27.0] - 2025-11-01

### Added

- **Marquee** [New]: Initial release of marquee component for continuously scrolling content

### Fixed

- **Angle Slider**: Resolved an issue where dragging the thumb from non-center positions caused unexpected value jumps.
  The thumb now maintains consistent positioning relative to the initial click point.

- **Slider**: Fixed a problem where the thumb offset shifted dynamically during dragging, resulting in value jumps. The
  offset now remains constant from the pointer throughout the drag operation.

- **Date Picker**: Resolved a crash in the range date picker occurring when users typed the end date first by
  implementing `null`/`undefined` checks for date property access.

- **Radio Group**: Reverted to `offsetLeft`/`offsetTop` calculations to restore correct indicator positioning within
  scrollable container contexts.

- **Tabs**: Reverted to `offsetLeft`/`offsetTop` calculations to fix indicator positioning issues in scrollable
  containers.

- **Tour**:
  - Corrected improper effect cleanup procedures
  - Fixed wait step functionality
  - Added step validation on mount to verify configuration validity

## [5.26.2] - 2025-10-18

### Fixed

- **Angle Slider**: Fix accessibility violation where the slider thumb element lacked an accessible name. The thumb now
  supports `aria-label` and `aria-labelledby` props, and automatically falls back to the label element's ID for proper
  ARIA labeling.

- **Select**: Fix accessibility violation where the required state was not set correctly to on the trigger.

- **Tags Input**: Fix issue where entering a custom tag with combobox integration required pressing `Enter` twice. The
  tags-input now correctly handles custom values when the combobox has no highlighted item (`aria-activedescendant` is
  empty), allowing the tag to be added on the first `Enter` press.

## [5.26.1] - 2025-10-15

### Fixed

- **Checkbox**
  - Fix issue where setting initial checked state to `indeterminate` doesn't work
  - Ensure `api.checkedState` returns the correct checked state (`boolean | "indeterminate"`)

- **Collapsible**: Fix issue where `dir` prop value was hardcoded to `ltr` instead of using the provided value

- **Combobox**: Fix issue where controlled single-select combobox does not propagate its initial value to `inputValue`

- **Listbox**: Fix issue where pressing Enter key when no highlighted item still calls `event.preventDefault()`

- **Radio Group**: Refactor to use `getBoundingClientRect()` for precise indicator positioning

- **Slider**
  - Fix issue where slider could stop abruptly when scrubbing thumb
  - Fix issue where range slider thumbs become stuck when dragged to the same position without `minStepsBetweenThumbs`

- **Tabs**: Refactor to use `getBoundingClientRect()` for precise indicator positioning

- **Tags Input**: Fix issue where `maxLength` doesn't apply to the edit input as well

## [5.26.0] - 2025-10-08

### Added

- **Collapsible**: Add support for `collapsedHeight` and `collapsedWidth` props to control the dimensions of the
  collapsible content when in its collapsed state.

- **Focus Trap**: Allow elements referenced by `aria-controls` to be included in the trap scope. This makes it possible
  for menus, popovers, etc. to be portalled and work correctly.

- **Pagination**: Add `getPageUrl` prop for generating `href` attributes when using pagination as links.

```ts
const service = useMachine(pagination.machine, {
  type: 'link',
  getPageUrl: ({ page, pageSize }) => `/products?page=${page}&size=${pageSize}`,
})
```

- **Select**: Add `SelectRootComponentProps` type export for better component type composition.

- **Listbox**: Add `ListboxRootComponentProps` type export for better component type composition.

- **Combobox**: Add `ComboboxRootComponentProps` type export for better component type composition.

- **TreeView**:
  - Add `TreeViewRootComponentProps` type export for better component type composition.
  - (Experimental) Add support for node renaming functionality:
    - Add `TreeViewNodeRenameInput` component for inline node label editing
    - Add `canRename` prop to control which nodes can be renamed
    - Add `onRenameStart`, `onBeforeRename`, and `onRenameComplete` callbacks for rename lifecycle
    - Add `CheckedChangeDetails`, `LoadChildrenErrorDetails`, `RenameStartDetails`, and `RenameCompleteDetails` type
      exports

### Fixed

- **Scroll Area**: Fix RTL horizontal scrollbar positioning on Safari

- **Slider**: Fix issue where slider continues dragging when disabled during drag operation.

- **Switch**: Fix issue where `data-active` is inconsistently applied when `disabled` state changes at runtime

## [5.25.1] - 2025-09-27

### Fixed

- **Date Picker**
  - Fix issue where year range picker doesn't show the hovered range
  - Fix issue where quarter presets returns incorrect date

- **FormatByte**: Add support for `unitSystem` property to allow changing between decimal (1000 bytes) and binary (1024
  bytes) systems.

- **Number Input**: When `formatOptions` is used (like `style: "currency"`), the cursor would jump to the end of the
  input when typing in the middle. The cursor now maintains its relative position during formatting changes.

- **Pin Input**: Fix issue where using the keyboard shortcuts `Cmd+Backspace` and `Cmd+Delete` to delete text in pin
  inputs would insert "undefined" instead of clearing the field.

- **Scroll Area**: Fix issue where resize tracking was not observing the root element, which caused the scrollbar to not
  update when the root element's size changed.

## [5.25.0] - 2025-09-16

### Added

- Added `mergeProps` utility for combining multiple props objects with proper event handler and className merging.
- Added `createContext` utility for creating typed React contexts with improved DX.

```tsx
import { createContext } from '@ark-ui/react/utils'
```

### Fixed

- **AngleSlider**: Export `angleSliderAnatomy` from the anatomy exports

## [5.24.1] - 2025-09-14

### Fixed

- **General**: Fix issue where `mergeProps` throws when `props` is `undefined` or `null`

## [5.24.0] - 2025-09-14

### Added

- **Combobox**: Add `alwaysSubmitOnEnter` prop to allow bypassing the default two-step behavior (Enter to close
  combobox, then Enter to submit form) and instead submit the form immediately on Enter press. This is useful for
  single-field autocomplete forms where Enter should submit the form directly.

- **Dismissable**: Add support for layer types in dismissable layer stack. Layers can now be categorized as `dialog`,
  `popover`, `menu`, or `listbox`. This enables:
  - `data-nested` attribute on nested layers of the same type
  - `data-has-nested` attribute on parent layers with nested children of the same type
  - `--nested-layer-count` CSS variable indicating the number of nested layers of the same type

### Changed

- **Hover Card**: Change default delay values for hover card to improve accessibility.
  - `openDelay`: from `700ms` to `600ms`

- **Tooltip**: Change default delay values for tooltip to improve accessibility.
  [Learn more](https://www.nngroup.com/articles/timing-exposing-content)
  - `openDelay`: from `1000ms` to `400ms`
  - `closeDelay`: from `500ms` to `150ms`

### Removed

- **TimePicker**: The TimePicker component has been removed from this release. This component was never part of the
  public API and was considered experimental. It had significant bugs and usability issues across all frameworks and
  locales, making it unsuitable for production use.

  **Migration**: We recommend building a custom time picker using the Select component for simple use cases, or
  implementing a time grid pattern for more complex scenarios.

### Fixed

- **Editable**: Allow text selection in editable preview when `autoResize` is enabled

  Previously, when `autoResize` was set to `true`, the preview element had `userSelect: "none"` applied, preventing
  users from selecting text. This has been fixed by removing the `userSelect` style property.

- **File Upload**: Fix regression where clicking the trigger doesn't open the file picker when used within the dropzone

- **Menu**:
  - Fix issue where keyboard activation of menu items with `target="_blank"` would open two tabs
  - Fix issue where hovering a partially visible item with pointer causes it to scroll into view

- **Tabs**: Fix issue where `ids` for `item` and `content` could not be customized

- **Toast**: Allow creating a toast store without any arguments

## [5.23.0] - 2025-09-08

### Added

- **Field**: Add `data-required` attribute to `Field.Label`
- **Select, Combobox, Listbox, TreeView**: Export `RootComponent` and `RootProviderComponent` types which are useful
  when building compositions that wrap the `Root` and `RootProvider` components and you still want type-safety for the
  collection.

### Fixed

- **Menu**: Fix `Menu.ItemText` not working inside `Menu.TriggerItem`

  ```tsx
  import { Select } from '@ark-ui/react/select'
  import { styled } from 'styling-lib'

  const Root = styled(Select.Root) as Select.RootComponent<{}>
  ```

## [5.22.0] - 2025-08-28

### Added

- **Combobox**: Add `ComboboxEmpty` component to display content when the combobox has no items

- **Listbox**: Add `ListboxEmpty` component to display content when the listbox has no items

- **Hover Card**: Add support for `disabled` prop

### Fixed

- **Collection**: Fix issue where disabled items could be reached via typeahead

- **Color Picker**: Fix issue where color picker was not working correctly in RTL mode

- **Date Picker**: Fix issue where datepicker doesn't revert to a valid value when the input value exceeds the min/max
  and blurred

- **Dismissable**: Expose `onRequestDismiss` custom event handler for event a parent layer requests the child layer to
  dismiss. If prevented via `event.preventDefault()`, the child layer will not dismiss when the parent layer is
  dismissed.

- **Number Input**
  - Omit the input `pattern` when `formatOptions` is provided. This prevents native pattern validation from conflicting
    with formatted values (e.g., currency or percent).
  - Handle empty values consistently across all format options.
  - Add `data-scrubbing` attribute to the number input parts.

- **Tags Input**: Fix issue where highlighted item doesn't clear when tabbing out of the input to an external button
  within the `control` part.

- **Tooltip**
  - Set `closeOnPointerdown` to `false` when `closeOnClick` is set to `false`
  - Reduce bundle size by replacing `@zag-js/store` dependency with a lightweight store implementation.

## [5.21.0] - 2025-08-24

### Added

- **Hooks**: Add `useAsyncList` and `useCollator` hooks for managing asynchronous list operations and locale-aware
  string comparison
- **Toast**: Export type definitions `ToastActionOptions`, `ToastPlacement`, `ToastPromiseOptions`, `ToastStatus`,
  `ToastStatusChangeDetails`, and `ToastType`

### Changed

- **Fieldset**
  - Update Legend component to render as `div` instead of `legend` element for improved styling flexibility
  - Add `aria-labelledby` attribute to fieldset root for better accessibility by linking to legend

### Fixed

- **Date Picker**
  - Clear hovered range state after completing range selection instead of waiting for pointer to leave the calendar
    area.
  - Fix issue where month and year select labels don't update correctly when using `min`/`max` constraints.
  - Expose `disabled` on `api.getMonths()` and `api.getYears()` results to indicate options out of range for current
    constraints.

- **Listbox**
  - Fix issue where first enabled item should be highlighted by default when listbox receives focus and no item is
    currently highlighted.
  - Add `getElement` to `scrollToIndexFn` details
  - Track collection changes and clear `highlightedValue` if the item is no longer in the collection.

- **Scroll Area**
  - Avoid detecting hover state from portalled descendants.
  - Add `data-dragging` attribute to scroll area parts.

- **Select**: Add `getElement` to `scrollToIndexFn` details

- **Combobox**: Add `getElement` to `scrollToIndexFn` details

- **Tabs**: Fix inconsistent keyboard navigation where TabPanel intermittently receives focus before focusable elements

## [5.20.0] - 2025-08-20

### Added

- **Highlight Word**: Add `exactMatch` option that enables whole-word matching using regex word boundaries.

### Fixed

- **Menu**: Fix context menu repositioning logic

- **ScrollArea**: Add `data-hover` to scroll area

## [5.19.0] - 2025-08-18

### Added

- **ScrollArea [NEW]**: Add support for new scroll area component.

### Fixed

- **ListCollection**
  - Avoid recomputing groups on every call to `at()` and `indexOf()`
  - Fixed bug in `find()` method (was checking `!= null` instead of `!== -1`)

- **GridCollection**: Avoid recomputing rows on every call to `getRows()`

- **Menu**
  - Add `data-state` attribute for context menu trigger
  - Fix context menu positioning bug where reopening at the same coordinates fails to reposition

## [5.18.4] - 2025-08-14

### Fixed

- **Listbox**: Add support for navigating grid collections

- **Carousel**:
  - Fix an issue where the carousel would not update when `slideCount` or `autoplay` props change.
  - Fix an issue where `loop: false` was ignored when using autoplay. Now, the carousel will stop when it gets to the
    last slide.

- **Date Picker**: Expose `data-inline` attribute on Content part to enable distinct styling for inline date pickers
  versus popover date pickers.

- **Menu**: Fix issue where `onCheckedChange` could be called twice on checkbox or radio item

- **Radio Group**: Fixed issue where arrow key navigation doesn't apply `data-focus-visible` on the newly focused item.

- **TagsInput**: Export `InputValueChangeDetails` type

### Changed

- **Async List**: Improve type inference for descriptors

## [5.18.3] - 2025-08-01

### Fixed

- **Factory**: Check if `children` is a valid React element before calling `Children.only()`

- **Carousel**: Fix issue where controlled carousel ignores last slide

## [5.18.2] - 2025-07-26

### Fixed

- **Dialog**
  - Sync content `--layer-index` with positioner and backdrop
  - Decouple `trapFocus` from `modal` so it's possible to set `modal=false` and `trapFocus=true`

## [5.18.1] - 2025-07-23

### Fixed

- **Date Picker**: Fixed issue where hovered range was connect to selected values, when it shouldn't

- **Tree View**: Fixed issue where tree view doesn't scroll into view when content overflows.

## [5.18.0] - 2025-07-22

### Added

- **Collection**: Add `useListSelection` hook for managing collection item selection with support for single/multiple
  selection modes

  ```jsx
  const collection = createListCollection({ items: ['React', 'Vue', 'Angular'] })
  const selection = useListSelection({ collection })

  // Check if item is selected
  const isSelected = selection.isSelected('React')

  // Select/deselect items
  selection.select('React')
  selection.toggle('Vue')
  ```

- **File Upload**: Add support for programmatically controlling the accepted files via `acceptedFiles` and
  `defaultAcceptedFiles`

- **Signature Pad**: Add support for programmatically controlling the paths via `paths` and `defaultPaths` props.

- **Date Picker**: Added hover range preview support for date picker range selection. Added `inHoveredRange`,
  `firstInHoveredRange`, and `lastInHoveredRange` properties to `DayTableCellState` with corresponding data attributes
  `data-in-hover-range`, `data-hover-range-start`, and `data-hover-range-end`.

  Hover range states are only active when not overlapping with actual selected range, enabling distinct styling for
  hover preview vs actual selection in range mode.

### Fixed

- **Date Picker**: Fix date comparison issues when time components are involved. This resolves critical issues with date
  comparison operations when different date types (`CalendarDate`, `CalendarDateTime`, `ZonedDateTime`) are mixed,
  particularly in scenarios involving time components.

## [5.17.0] - 2025-07-18

### Added

- **Checkbox**: Add `CheckboxGroupProvider` component for external checkbox group state management

### Fixed

- **Carousel**: Fix issue where full page carousel could trap scrolling

- **ListCollection**:Export `UseListCollectionReturn` type

- **TreeCollection**: Fix issue where the `filter` method completely deletes the children key from the node when there
  are no matching children

- **Number Input**: Fix issue where default pattern does not allow negative numbers with decimal point

- **File Upload**
  - Export `FileError`, `FileMimeType`, and `FileRejection` types
  - Fix issue where calling `api.setFiles` invokes validation with incorrect `acceptedFiles`
  - Fix issue where the browser might not be able to infer the mime type of a file due to limitations, drag source or
    security restrictions. As a fallback in the file validation logic, we now infer the mime type from the file
    extension.

## [5.16.1] - 2025-07-05

### Fixed

- **Combobox**
  - Expose `reason` to `onOpenChange` and `onInputValueChange` callbacks
  - Expose `api.clearHighlightedValue` function to clear highlighted value

- **Date Picker**
  - Fix issue where datepicker errors when setting `selectionMode=range` and `minView=year`
  - Fix issue where `focusedValue` could not be fully controlled

- **Toast**: Fix issue where toast `title` or `description` could not accept React element

- **Listbox**: Select highlighted item only if it exists in the collection

- **Progress**: Improve `valueAsString` formatting

- **Select**
  - Select highlighted item only if it exists in the collection
  - Expose `api.clearHighlightedValue` function to clear highlighted value

- **Tour**: Fix an issue where the `goto` function in `StepActionMap` doesn't work when passing step IDs (string)

- **Tree View**: Expose `id` in the tree node state

- **ClientOnly**: Support `children` as a function

## [5.16.0] - 2025-07-01

### Added

- **Color Picker**: Add support for `inline` prop to render color picker inline
- **Date Picker**: Add support for `inline` prop to render the date calendar inline

### Fixed

- **Color Picker**: Auto-prefix Hex values with `#` if missing when using the `hex` channel input
- **Menu**: Fix interaction outside detection for focusable context trigger
- **Tree View**: Improve support for rendering tree items as links

## [5.15.4] - 2025-06-27

### Fixed

- **Combobox, Select, Listbox**: Fix issue where rehydrating `defaultValue` or `value` after fetching items doesn't
  update the `valueAsString`

## [5.15.3] - 2025-06-27

### Fixed

- **Tree View**: Fix tree traversal for querying last node

## [5.15.2] - 2025-06-26

### Fixed

- **Date Picker**: Fix issue with keyboard selection where setting unavailable date causes month view to behave
  differently from clicking with mouse

- **Toast**: Fix issue where app crashes when `toaster.promise` is called without loading option. The `loading` option
  is now required. A warning will be logged if it is not provided

- **Tree View**
  - Fix issue where clicking a branch with indeterminate state doesn't check its child nodes
  - Remove `aria-busy` attribute from branch trigger when not loading children
  - Expose node details in `onExpandChange`, `onSelectionChange` and `onFocusChange`

- **Angle Slider**: Fix issue where scrubbing doesn't feel smooth on touch devices

- **Timer**:
  - Fix issue where timer could continue beyond `targetMs` when window is not visible
  - Add validation to ensure `startMs` and `targetMs` are configured correctly
  - Fix `progressPercent` calculation for countdown timers

## [5.15.1] - 2025-06-23

### Fixed

- **Listbox**: Fix issue where `Listbox.ItemContext` was not exported

## [5.15.0] - 2025-06-23

### Added

- **Tree View**
  - Add support for checkbox state for checkbox trees via `defaultCheckedValue`, `checkedValue`, `onCheckedChange` props
  - Add callback for when `loadChildren` fails via `onLoadChildrenError` prop

### Fixed

- **Progress**
  - Fix issue where setting orientation to `vertical` don't work
  - Fix issue where setting `defaultValue` to `null` doesn't show indeterminate state

## [5.14.2] - 2025-06-19

### Fixed

- **General**: Ensure pointerdown or click event handlers only execute when the main button is clicked
- **Tree View**: Exported `TreeViewNodeState` and `TreeViewNodeProps` types from `@zag-js/tree-view`

### Changed

- **Collection**: Improve the APIs around `tree.flatten(...)` and `flattenedToTree` to ensure the original node
  properties are preserved.

  > Previously, `tree.flatten()` would return an array of objects with `value` and `label` stripping out the original
  > node properties.

  ```ts
  const tree = new TreeCollection({
    rootNode: {
      value: 'ROOT',
      children: [{ value: 'child1' }, { value: 'child2' }],
    },
  })

  const flattened = tree.flatten()
  const reconstructed = flattenedToTree(flattened)

  console.log(reconstructed.rootNode)

  // {
  //   value: "ROOT",
  //   children: [{ value: "child1" }, { value: "child2" }],
  // }
  ```

## [5.14.1] - 2025-06-17

### Fixed

- **Popover**: Fixed issue where `onOpenChange` could be called twice when controlled
- **File Utils**: Improved `downloadFile` function to handle webview scenarios
- **Combobox**:
  - Fixed issue where `onInputValueChange` could be called twice when selecting an item
  - Fixed issue where combobox with `allowCustomValue: true` used within in a form requires two enter keypress to submit

## [5.14.0] - 2025-06-10

### Added

- **Editable**: Added support for `activationMode=none`
- **Collection**
  - Exposed `copy` method
  - Added support for `getParentNodes` to accept a value or index path

### Fixed

- **Collection**: Fixed issue where entrypoint `@ark-ui/react/collection` was not working as expected
- **Carousel**: Fixed issue where carousel crashes when `slidesPerPage` is 0
- **File Upload**: Prevented `undefined` in `acceptedFiles` when no files accepted
- **Select**: Fixed issue where highlighted item could be cleared when navigating up/down the list with keyboard
- **Tabs**: Fixed issue where tabs with links should not trigger tab change upon cmd/middle click
- **Menu**: Fixed issue where `Menu.ItemText` could not be used with `Menu.Item`

## [5.13.0] - 2025-06-07

### Added

- **Collection**: Added new `useListCollection` hook to create a dynamic list collection.

### Fixed

- **Progress**: Exported `ProgressValueChangeDetails` and `ProgressValueTranslationDetails` types from
  `@zag-js/progress`

## [5.12.0] - 2025-06-05

### Added

- **Tree View**: Added support for lazy loading node children. To use this, you need to provide:
  - `loadChildren` is a function that is used to load the children of a node.
  - `onLoadChildrenComplete` is a callback that is called when the children of a node are loaded. Used to update the
    tree collection.
  - Add `childrenCount` to the node object to indicate the number of children.

### Fixed

- **Slider**
  - Fixed issue where `Shift` + `ArrowRight` set value to `0` instead of `max` when step is too large (e.g. `20`)
  - Fixed issue where `onValueChangeEnd` doesn't return the latest value when dragging very fast

## [5.11.0] - 2025-05-30

### Added

- **File Upload**: Added support for transforming uploaded files via `transformFiles` context property.

### Fixed

- **Slider**: Fixed issue where `minStepsBetweenThumbs` isn't computed correctly when interacting with pointer or
  keyboard.

## [5.10.0] - 2025-05-29

### Added

- **[NEW] Password Input**: Added `PasswordInput` component for creating password inputs

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'

export const Basic = () => (
  <PasswordInput.Root>
    <PasswordInput.Label>Password</PasswordInput.Label>
    <PasswordInput.Control>
      <PasswordInput.Input />
      <PasswordInput.VisibilityTrigger>
        <PasswordInput.Indicator fallback={<EyeOffIcon />}>
          <EyeIcon />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
)
```

- **Select**: Added `onSelect` callback that gets fired when an item is selected via keyboard/mouse.

### Fixed

- **Color Picker**: Fixed issue where value change end event is invoked when committing via an input.

- **Toast**: Fixed issue where calling `toast.remove()` without an id shows a TypeScript error.

- **Field**: Fixed issue where helper text and error text could not be detected in shadow DOM environments.

## [5.9.2] - 2025-05-24

### Fixed

- **Collection**: Export `CollectionOptions`, `TreeCollectionOptions`, `GridCollectionOptions` types.

- **Carousel**
  - Fixed issue where focusing on carousel region and navigating with keyboard doesn't work as expected
  - Fixed issue when `allowMouseDrag` is set where carousel no longer snaps after mouse interaction

- **Combobox**: Fixed issue where `onInputValueChange` doesn't get called when `autoFocus` is set to `true`

- **Slider**: Fixed issue where slider could throw a error when rendered in an popover or dialog

- **Tour**: Fixed issue where calling `api.start(<id>)` with a step id doesn't work as expected

## [5.9.1] - 2025-05-12

### Fixed

- **Combobox**: Fixed issue where `focusable` prop was not being applied to the trigger element.

- **Collection**: Fixed issue where `getNextValue` and `getPreviousValue` doesn't work as expected when `groupBy` is
  used.

## [5.9.0] - 2025-05-05

### Added

- **Locale**: Added `useFilter` hook to filter data based on the current locale.
- **Format**: Added `FormatRelativeTime` component for formatting relative time.

## [5.8.0] - 2025-05-01

### Added

- **Date Picker**: Added support for `outsideDaySelectable` prop to allow selecting days outside the current month (on
  the same visible date range)

### Fixed

- **Collapsible**: Fixed issue in React.js <= v18.x where collapse animation might not work as expected

## [5.7.0] - 2025-04-25

### Added

- **[NEW] Listbox**: Introduced the `Listbox` component for selecting a single or multiple items from a list. See the
  [documentation](https://ark-ui.com/docs/components/listbox) for details.
- Improved support for grouping collection items. Check the `Listbox`, `Select` or `Combobox` documentation for more
  details.

### Changed

- Added `package.json` to `exports` for improved compatibility with tools like Vite.

## [5.6.0] - 2025-04-15

### Added

- **[NEW] AngleSlider**: Introduced the `AngleSlider` component for selecting an angle. See the
  [documentation](https://ark-ui.com/docs/components/angle-slider) for details.
- **[NEW] FloatingPanel**: Introduced the `FloatingPanel` component for creating floating windows. See the
  [documentation](https://ark-ui.com/docs/components/floating-panel) for details.
- **Toast**: Added toast queuing when the max limit is reached:
  - New toasts were queued instead of dropped
  - Queued toasts were shown when space became available
  - Queue cleared when all toasts were removed
- **Combobox**:
  - Fallbacked to the trigger element as the positioning anchor
  - Added `data-empty` attribute to indicate an empty listbox or content

## [5.5.0] - 2025-04-05

### Added

- **Presence**: Added support for skipping the initial animation when the component is mounted. This can be used in all
  disclosure components (e.g., `Dialog`, `DatePicker`, `Menu` etc).

### Fixed

- **Tabs**: Fixed issue where tabs indicator animation behaves inconsistently.

- **Date Picker**
  - Fixed issue where datepicker throws error when navigating month view.
  - Fixed issue where range selection doesn't reset correctly when clicking the same start date.

- **Disclosure Components**
  - Fixed issue where pointerdown outside doesn't work consistently on mobile devices.
  - Improved pointerdown outside click detection in shadow DOM environments.

## [5.4.0] - 2025-03-28

### Added

- **Slider**
  - Add support for `origin: end` to align the thumb to the end of the track.
  - Expose `thumbSize` as CSS variables in the root element. Can be useful for styling the slider.

- **Menu**
  - Added `onSelect` event to the `Menu.Item` component.

### Fixed

- Ensured each component's state machine starts before processing events.
- **HoverCard, ColorPicker**: Added missing `tabIndex` for better dialog support.
- **Menu**: Assigned unique IDs to menu items to improve accessibility and HTML validation.

## [5.3.1] - 2025-03-24

### Fixed

- Fixed an issue where a function was imported from a package that wasn't declared as a dependency.

## [5.3.0] - 2025-03-24

### Added

- **Collapsible**: Added an `Indicator` part to display whether the collapsible was open or closed.
- **ColorPicker**: Added support for formatting the `ValueText` component.

```tsx
<ColorPicker.ValueText format="hex" /> // #ff0000
```

### Fixed

- **Combobox**: Fixed an issue where `onOpenChange` was called with the same `open` value.
- **DownloadTrigger**: Added the missing `use client` directive.
- **Splitter**: Fixed an issue where `onResizeStart` and `onResizeEnd` callbacks weren't triggered during keyboard
  interactions.

## [5.2.0] - 2025-03-22

### Added

- **[NEW] DownloadTrigger**: Added Component for downloading a blob or file, whether retrieved synchronously or
  asynchronously.

```tsx
import { DownloadTrigger } from '@ark-ui/react/download-trigger'

export const DownloadImage = () => {
  async function fetchImage() {
    const response = await fetch('https://picsum.photos/200/300')
    return response.blob()
  }

  return (
    <DownloadTrigger data={fetchImage} fileName="avatar.jpeg" mimeType="image/jpeg">
      Download Image
    </DownloadTrigger>
  )
}
```

### Changed

- **NumberInput**: Set the default step to `0.01` when `formatOptions.style` was set to `percent`.
- **[Breaking] Splitter**: Redesigned splitter machine to support more use cases and improve DX. Check out the
  [Splitter](https://ark-ui.com/docs/components/splitter) documentation for more details.

### Fixed

- **Toast**: Fixed issue where setting `offsets` to `undefined` caused the machine to throw.
- **Select**: Fixed issue where select `valueAsString` lost reactivity.

## [5.1.0] - 2025-03-17

### Added

- Added support for a cleanup function in `ref`.

### Fixed

- **Field**: Exported the missing `useField` hook.
- **NumberInput**: `onValueChange` correctly received `valueAsNumber`.
- **Slider**: Thumbs initialized correctly when `min` was set to a non-zero value.

## [5.0.1] - 2025-03-11

### Fixed

- Effects now flush synchronously instead of using a microtask.
- **Checkbox**: `data-invalid` is no longer set when `invalid` is `false`.
- **Combobox**: Fixed unexpected cursor movement when editing input.
- **PinInput**: OTP SMS autofill now works as expected.
- **RatingGroup**: Fixed incorrect focus placement on the label.
- **TagsInput**: Improved caret detection to prevent unintended tag removal.
- **Timer**
  - Fixed slowdown when switching tabs/windows.
  - Changed default `interval` from `250` to `1000`.

## [5.0.0] - 2025-03-06

Ark UI just got a major performance boost! 🚀

### What’s new in v5?

- **Blazing-fast performance** – Every component runs smoother and renders faster.
- **Smaller bundle size** – Leaner components and adapters for a more efficient build.

We made this happen by using React’s native reactive primitives instead of external stores.

In our stress tests with **10,000 components**, Ark v5 delivered **1.5x–4x** better performance across the board.

![Performance comparison showing Ark v5 is 1.5x-4x faster than other libraries](./v5.svg)

### A quick note on tests

Most component updates are non-breaking, but due to this change, some tests may need adjustments. For example:

```jsx
// Before
it('should open by default', () => {
  render(<ComponentUnderTest defaultOpen />)
  expect(screen.getByRole('dialog')).toBeInTheDocument()
})

// After
it('should open by default', async () => {
  render(<ComponentUnderTest defaultOpen />)
  expect(await screen.findByRole('dialog')).toBeInTheDocument()
})
```

#### Added

- **Carousel**: ⚠️ Breaking change: Added required prop `slideCount` to `Carousel.Root` component.
- **Clipboard**: Added `onValueChange` and `defaultValue` props.
- **ColorPicker**: Added `defaultFormat` prop.
- **Combobox**: Added `defaultHighlightedValue` and `defaultInputValue` props.
- **DatePicker**: Added `defaultFocusedValue` prop, `getViewProps`, and `visibleRangeText`.
- **HoverCard**: Expanded interaction handlers.
- **Menu**: Added `defaultHighlightedValue` prop.
- **Pagination**: Added `defaultPageSize` prop.
- **PinInput**: Added `count` prop for better SSR aria-label.
- **Progress**: Added `locale` and `formatOptions` props.
- **QrCode**: Added `pixelSize` prop.
- **Select**: Added `defaultHighlightedValue` prop.
- **TagsInput**: Added `defaultInputValue` prop.
- **Toggle**: Reintroduced toggle machine.

#### Fixed

- **Accordion**: Fixed issue in Safari where clicking triggers didn't show content.
- **Avatar**: Fixed `api.setSrc` not working.
- **Carousel**: Fixed pagination sync and initial page issues.
- **File Upload**: Fixed drag-and-drop when `directory: true`.
- **Menu**: Fixed context menu positioning not updating on right-click.
- **Number Input**: Fixed `value` prop not being consumed.
- **Pin Input**: Fixed focus warnings and editing issues.
- **Progress**: Allowed more precise (decimal) values.
- **Radio Group, Switch**: Improved focus behavior in Safari.
- **Select**: Fixed regression where `multiple: true` didn't work.
- **Steps**: Ensured ARIA attributes use valid values and wrapped `<li>` elements correctly within `<ul>` or `<ol>`.
- **Textarea**: Fixed `ResizeObserver` warning.
- **Timer**: Fixed stopping issue when switching tabs; resolved issue where `action` prop was passed to `ActionTrigger`.
- **Toast**: Fixed keyboard navigation skipping close button.
- **Toggle Group**: Fixed `data-focus` not being removed on blur.