# OVERVIEW --- # Getting Started (REACT) ## Quickstart Running tight on schedule? No worries! Check out our quickstart examples to get started with Ark UI in seconds. - [Next.js Template](https://stackblitz.com/edit/github-qcm2dskf) - [Solid Start Template](https://stackblitz.com/edit/github-1hgkbbln) - [Nuxt Template](https://stackblitz.com/edit/github-s3sg6syq) ## Setup Guide Before you start, ensure you have a proper project setup. If not, follow your preferred application framework setup guide and then return to this guide. Install the Ark UI dependency using your preferred package manager. ```bash npm install @ark-ui/react // or pnpm install @ark-ui/react // or yarn add @ark-ui/react // or bun add @ark-ui/react ``` In this guide, we will be adding a Slider component. Copy the following code to your project. Ark UI is a headless component library that doesn't include default styles. You can leverage the `data-scope` and `data-part` attributes to style your components with custom CSS. For example, to style a slider component, you can target its parts using these attributes: ```css /* Targets the */ [data-scope='slider'][data-part='root'] { display: flex; flex-direction: column; } ``` Check out the [Styling Components guide](/react/docs/guides/styling) to learn more about styling components in Ark UI. Congratulations! You've successfully set up and styled your components using Ark UI. If you run into any issues or have questions, open an issue on our [GitHub](https://github.com/chakra-ui/ark/issues/new/choose) or reach out on [Discord](https://discord.gg/ww6HE5xaZ2). Happy hacking! ✌️ # Getting Started (VUE) ## Quickstart Running tight on schedule? No worries! Check out our quickstart examples to get started with Ark UI in seconds. - [Next.js Template](https://stackblitz.com/edit/github-qcm2dskf) - [Solid Start Template](https://stackblitz.com/edit/github-1hgkbbln) - [Nuxt Template](https://stackblitz.com/edit/github-s3sg6syq) ## Setup Guide Before you start, ensure you have a proper project setup. If not, follow your preferred application framework setup guide and then return to this guide. Install the Ark UI dependency using your preferred package manager. ```bash npm install @ark-ui/vue // or pnpm install @ark-ui/vue // or yarn add @ark-ui/vue // or bun add @ark-ui/vue ``` In this guide, we will be adding a Slider component. Copy the following code to your project. Ark UI is a headless component library that doesn't include default styles. You can leverage the `data-scope` and `data-part` attributes to style your components with custom CSS. For example, to style a slider component, you can target its parts using these attributes: ```css /* Targets the */ [data-scope='slider'][data-part='root'] { display: flex; flex-direction: column; } ``` Check out the [Styling Components guide](/react/docs/guides/styling) to learn more about styling components in Ark UI. Congratulations! You've successfully set up and styled your components using Ark UI. If you run into any issues or have questions, open an issue on our [GitHub](https://github.com/chakra-ui/ark/issues/new/choose) or reach out on [Discord](https://discord.gg/ww6HE5xaZ2). Happy hacking! ✌️ # Getting Started (SVELTE) ## Quickstart Running tight on schedule? No worries! Check out our quickstart examples to get started with Ark UI in seconds. - [Next.js Template](https://stackblitz.com/edit/github-qcm2dskf) - [Solid Start Template](https://stackblitz.com/edit/github-1hgkbbln) - [Nuxt Template](https://stackblitz.com/edit/github-s3sg6syq) ## Setup Guide Before you start, ensure you have a proper project setup. If not, follow your preferred application framework setup guide and then return to this guide. Install the Ark UI dependency using your preferred package manager. ```bash npm install @ark-ui/svelte // or pnpm install @ark-ui/svelte // or yarn add @ark-ui/svelte // or bun add @ark-ui/svelte ``` In this guide, we will be adding a Slider component. Copy the following code to your project. Ark UI is a headless component library that doesn't include default styles. You can leverage the `data-scope` and `data-part` attributes to style your components with custom CSS. For example, to style a slider component, you can target its parts using these attributes: ```css /* Targets the */ [data-scope='slider'][data-part='root'] { display: flex; flex-direction: column; } ``` Check out the [Styling Components guide](/react/docs/guides/styling) to learn more about styling components in Ark UI. Congratulations! You've successfully set up and styled your components using Ark UI. If you run into any issues or have questions, open an issue on our [GitHub](https://github.com/chakra-ui/ark/issues/new/choose) or reach out on [Discord](https://discord.gg/ww6HE5xaZ2). Happy hacking! ✌️ # Getting Started (SOLID) ## Quickstart Running tight on schedule? No worries! Check out our quickstart examples to get started with Ark UI in seconds. - [Next.js Template](https://stackblitz.com/edit/github-qcm2dskf) - [Solid Start Template](https://stackblitz.com/edit/github-1hgkbbln) - [Nuxt Template](https://stackblitz.com/edit/github-s3sg6syq) ## Setup Guide Before you start, ensure you have a proper project setup. If not, follow your preferred application framework setup guide and then return to this guide. Install the Ark UI dependency using your preferred package manager. ```bash npm install @ark-ui/solid // or pnpm install @ark-ui/solid // or yarn add @ark-ui/solid // or bun add @ark-ui/solid ``` In this guide, we will be adding a Slider component. Copy the following code to your project. Ark UI is a headless component library that doesn't include default styles. You can leverage the `data-scope` and `data-part` attributes to style your components with custom CSS. For example, to style a slider component, you can target its parts using these attributes: ```css /* Targets the */ [data-scope='slider'][data-part='root'] { display: flex; flex-direction: column; } ``` Check out the [Styling Components guide](/react/docs/guides/styling) to learn more about styling components in Ark UI. Congratulations! You've successfully set up and styled your components using Ark UI. If you run into any issues or have questions, open an issue on our [GitHub](https://github.com/chakra-ui/ark/issues/new/choose) or reach out on [Discord](https://discord.gg/ww6HE5xaZ2). Happy hacking! ✌️ # Changelog (REACT) ## [Unreleased] ### Added - **Locale**: Added `useDateFormatter` hook for localized date formatting using `@internationalized/date` ## [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 = () => ( Password }> ) ``` - **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()` 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 // #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 ( Download Image ) } ``` ### 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() expect(screen.getByRole('dialog')).toBeInTheDocument() }) // After it('should open by default', async () => { render() 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 `
  • ` elements correctly within `
      ` or `
        `. - **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. # Changelog (VUE) ## [Unreleased] ### Added - **Locale**: Added `useDateFormatter` hook for localized date formatting using `@internationalized/date` ## [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 = () => ( Password }> ) ``` - **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()` 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 // #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 ( Download Image ) } ``` ### 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() expect(screen.getByRole('dialog')).toBeInTheDocument() }) // After it('should open by default', async () => { render() 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 `
      1. ` elements correctly within `
          ` or `
            `. - **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. # Changelog (SVELTE) ## [Unreleased] ### Added - **Locale**: Added `useDateFormatter` hook for localized date formatting using `@internationalized/date` ## [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 = () => ( Password }> ) ``` - **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()` 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 // #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 ( Download Image ) } ``` ### 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() expect(screen.getByRole('dialog')).toBeInTheDocument() }) // After it('should open by default', async () => { render() 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 `
          1. ` elements correctly within `
              ` or `
                `. - **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. # Changelog (SOLID) ## [Unreleased] ### Added - **Locale**: Added `useDateFormatter` hook for localized date formatting using `@internationalized/date` ## [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 = () => ( Password }> ) ``` - **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()` 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 // #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 ( Download Image ) } ``` ### 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() expect(screen.getByRole('dialog')).toBeInTheDocument() }) // After it('should open by default', async () => { render() 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 `
              1. ` elements correctly within `
                  ` or `
                    `. - **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. # About Ark UI (REACT) ## Motivation Most popular UI component libraries are designed to work with a specific JavaScript framework. Building UI components that work across different JavaScript frameworks presents significant challenges for organizations working with diverse technology stacks. ## Solution Ark UI provides components for building complex, interactive, and accessible user interfaces across multiple JavaScript frameworks. To achieve this, Ark UI is built on top of [Zag.js](https://zagjs.com), a UI component library powered by Finite State Machines. Check out the architecture diagram below for a high-level overview. ## Team Ark UI is built and maintained by the team behind [Chakra UI](https://chakra-ui.com). - [Segun Adebayo](https://github.com/segunadebayo) - Creator of Chakra UI and Zag.js - [Christian Busch](https://github.com/cschroeter) - Core maintainer - [Esther Agbaje](https://github.com/estheragbaje) - Developer Advocate ## Acknowledgments We are committed to open source and the power of collaboration. Our work has been inspired by numerous projects and individuals who continually drive us to innovate and improve. - [Zag.js](https://zagjs.com/) - The foundation of this project - [Park UI](https://park-ui.com) - For providing the styled component demos featured in this project - [Radix Vue](https://www.radix-vue.com/) - For `useForwardPropsEmits`, which we re-export to build closed Vue components ## License This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ark/blob/main/LICENSE). # About Ark UI (VUE) ## Motivation Most popular UI component libraries are designed to work with a specific JavaScript framework. Building UI components that work across different JavaScript frameworks presents significant challenges for organizations working with diverse technology stacks. ## Solution Ark UI provides components for building complex, interactive, and accessible user interfaces across multiple JavaScript frameworks. To achieve this, Ark UI is built on top of [Zag.js](https://zagjs.com), a UI component library powered by Finite State Machines. Check out the architecture diagram below for a high-level overview. ## Team Ark UI is built and maintained by the team behind [Chakra UI](https://chakra-ui.com). - [Segun Adebayo](https://github.com/segunadebayo) - Creator of Chakra UI and Zag.js - [Christian Busch](https://github.com/cschroeter) - Core maintainer - [Esther Agbaje](https://github.com/estheragbaje) - Developer Advocate ## Acknowledgments We are committed to open source and the power of collaboration. Our work has been inspired by numerous projects and individuals who continually drive us to innovate and improve. - [Zag.js](https://zagjs.com/) - The foundation of this project - [Park UI](https://park-ui.com) - For providing the styled component demos featured in this project - [Radix Vue](https://www.radix-vue.com/) - For `useForwardPropsEmits`, which we re-export to build closed Vue components ## License This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ark/blob/main/LICENSE). # About Ark UI (SVELTE) ## Motivation Most popular UI component libraries are designed to work with a specific JavaScript framework. Building UI components that work across different JavaScript frameworks presents significant challenges for organizations working with diverse technology stacks. ## Solution Ark UI provides components for building complex, interactive, and accessible user interfaces across multiple JavaScript frameworks. To achieve this, Ark UI is built on top of [Zag.js](https://zagjs.com), a UI component library powered by Finite State Machines. Check out the architecture diagram below for a high-level overview. ## Team Ark UI is built and maintained by the team behind [Chakra UI](https://chakra-ui.com). - [Segun Adebayo](https://github.com/segunadebayo) - Creator of Chakra UI and Zag.js - [Christian Busch](https://github.com/cschroeter) - Core maintainer - [Esther Agbaje](https://github.com/estheragbaje) - Developer Advocate ## Acknowledgments We are committed to open source and the power of collaboration. Our work has been inspired by numerous projects and individuals who continually drive us to innovate and improve. - [Zag.js](https://zagjs.com/) - The foundation of this project - [Park UI](https://park-ui.com) - For providing the styled component demos featured in this project - [Radix Vue](https://www.radix-vue.com/) - For `useForwardPropsEmits`, which we re-export to build closed Vue components ## License This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ark/blob/main/LICENSE). # About Ark UI (SOLID) ## Motivation Most popular UI component libraries are designed to work with a specific JavaScript framework. Building UI components that work across different JavaScript frameworks presents significant challenges for organizations working with diverse technology stacks. ## Solution Ark UI provides components for building complex, interactive, and accessible user interfaces across multiple JavaScript frameworks. To achieve this, Ark UI is built on top of [Zag.js](https://zagjs.com), a UI component library powered by Finite State Machines. Check out the architecture diagram below for a high-level overview. ## Team Ark UI is built and maintained by the team behind [Chakra UI](https://chakra-ui.com). - [Segun Adebayo](https://github.com/segunadebayo) - Creator of Chakra UI and Zag.js - [Christian Busch](https://github.com/cschroeter) - Core maintainer - [Esther Agbaje](https://github.com/estheragbaje) - Developer Advocate ## Acknowledgments We are committed to open source and the power of collaboration. Our work has been inspired by numerous projects and individuals who continually drive us to innovate and improve. - [Zag.js](https://zagjs.com/) - The foundation of this project - [Park UI](https://park-ui.com) - For providing the styled component demos featured in this project - [Radix Vue](https://www.radix-vue.com/) - For `useForwardPropsEmits`, which we re-export to build closed Vue components ## License This project is licensed under the terms of the [MIT license](https://github.com/chakra-ui/ark/blob/main/LICENSE). # GUIDES --- # Styling (REACT) ## Overview Ark UI is a headless component library that works with any styling solution. It provides functional styles for elements like popovers for positioning, while leaving presentation styles up to you. Some components also expose CSS variables that can be used for styling or animations. > **Tip:** Looking for a ready-to-use solution? Checkout [Park UI](https://park-ui.com) for a collection of pre-designed > styles based on Ark UI components. ### Data Attributes Ark UI components use `data-scope` and `data-part` attributes to target specific elements within a component. Interactive components often include `data-*` attributes to indicate their state. For example, here's what an open accordion item looks like: ```html
                    ``` For more details on each component's data attributes, refer to their respective documentation. ## Styling with CSS When styling components with CSS, you can target the data attributes assigned to each component part for easy customization. ### Styling a Part To style a specific component part, target its `data-scope` and `data-part` attributes: ```css [data-scope='accordion'][data-part='item'] { border-bottom: 1px solid #e5e5e5; } ``` ### Styling a State To style a component based on its state, use the `data-state` attribute: ```css [data-scope='accordion'][data-part='item'][data-state='open'] { background-color: #f5f5f5; } ``` > **Tip:** If you prefer using classes instead of data attributes, utilize the `class` or `className` prop to add custom > classes to Ark UI components. ### Class Names If you prefer using classes instead of data attributes, utilize `class` or `className` prop to add custom classes to Ark UI components. Pass a class: ```jsx {/* … */} ``` Then use in styles: ```css .AccordionItem { border-bottom: 1px solid #e5e5e5; &[data-state='open'] { background-color: #f5f5f5; } } ``` ## Styling with Panda CSS [Panda CSS](https://panda-css.com) is a best-in-class CSS-in-JS framework that integrates seamlessly with Ark UI, providing an efficient styling solution. ### Styling a part Panda offers various ways to write styles, but in the context of Ark UI, we recommend using the `defineSlotRecipe` function to style a component with its different parts and variants. > **Important:** When importing anatomy objects, we recommend using the `@ark-ui//anatomy` entrypoint (e.g., > `@ark-ui/react/anatomy`) instead of the main package export to avoid potential build and import errors. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid #e5e5e5', }, }, defaultVariants: {}, variants: {}, }) ``` ### Styling a state To style a component based on its state, you can use built in [conditions](https://panda-css.com/docs/customization/conditions) in Panda CSS. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid {colors.gray.300}', _open: { // [!code highlight] backgroundColor: 'gray.100', }, }, }, defaultVariants: {}, variants: {}, }) ``` ## Styling with Tailwind CSS [Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework providing a flexible way to style your components. ### Styling a Part To style a part, apply classes directly to the parts using either `class` or `className`, depending on the JavaScript framework. ```jsx {/* … */} ``` ### Styling a State Leverage Tailwind CSS's variant selector to style a component based on its data-state attribute. ```jsx {/* … */} ``` # Styling (VUE) ## Overview Ark UI is a headless component library that works with any styling solution. It provides functional styles for elements like popovers for positioning, while leaving presentation styles up to you. Some components also expose CSS variables that can be used for styling or animations. > **Tip:** Looking for a ready-to-use solution? Checkout [Park UI](https://park-ui.com) for a collection of pre-designed > styles based on Ark UI components. ### Data Attributes Ark UI components use `data-scope` and `data-part` attributes to target specific elements within a component. Interactive components often include `data-*` attributes to indicate their state. For example, here's what an open accordion item looks like: ```html
                    ``` For more details on each component's data attributes, refer to their respective documentation. ## Styling with CSS When styling components with CSS, you can target the data attributes assigned to each component part for easy customization. ### Styling a Part To style a specific component part, target its `data-scope` and `data-part` attributes: ```css [data-scope='accordion'][data-part='item'] { border-bottom: 1px solid #e5e5e5; } ``` ### Styling a State To style a component based on its state, use the `data-state` attribute: ```css [data-scope='accordion'][data-part='item'][data-state='open'] { background-color: #f5f5f5; } ``` > **Tip:** If you prefer using classes instead of data attributes, utilize the `class` or `className` prop to add custom > classes to Ark UI components. ### Class Names If you prefer using classes instead of data attributes, utilize `class` or `className` prop to add custom classes to Ark UI components. Pass a class: ```jsx {/* … */} ``` Then use in styles: ```css .AccordionItem { border-bottom: 1px solid #e5e5e5; &[data-state='open'] { background-color: #f5f5f5; } } ``` ## Styling with Panda CSS [Panda CSS](https://panda-css.com) is a best-in-class CSS-in-JS framework that integrates seamlessly with Ark UI, providing an efficient styling solution. ### Styling a part Panda offers various ways to write styles, but in the context of Ark UI, we recommend using the `defineSlotRecipe` function to style a component with its different parts and variants. > **Important:** When importing anatomy objects, we recommend using the `@ark-ui//anatomy` entrypoint (e.g., > `@ark-ui/react/anatomy`) instead of the main package export to avoid potential build and import errors. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid #e5e5e5', }, }, defaultVariants: {}, variants: {}, }) ``` ### Styling a state To style a component based on its state, you can use built in [conditions](https://panda-css.com/docs/customization/conditions) in Panda CSS. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid {colors.gray.300}', _open: { // [!code highlight] backgroundColor: 'gray.100', }, }, }, defaultVariants: {}, variants: {}, }) ``` ## Styling with Tailwind CSS [Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework providing a flexible way to style your components. ### Styling a Part To style a part, apply classes directly to the parts using either `class` or `className`, depending on the JavaScript framework. ```jsx {/* … */} ``` ### Styling a State Leverage Tailwind CSS's variant selector to style a component based on its data-state attribute. ```jsx {/* … */} ``` # Styling (SVELTE) ## Overview Ark UI is a headless component library that works with any styling solution. It provides functional styles for elements like popovers for positioning, while leaving presentation styles up to you. Some components also expose CSS variables that can be used for styling or animations. > **Tip:** Looking for a ready-to-use solution? Checkout [Park UI](https://park-ui.com) for a collection of pre-designed > styles based on Ark UI components. ### Data Attributes Ark UI components use `data-scope` and `data-part` attributes to target specific elements within a component. Interactive components often include `data-*` attributes to indicate their state. For example, here's what an open accordion item looks like: ```html
                    ``` For more details on each component's data attributes, refer to their respective documentation. ## Styling with CSS When styling components with CSS, you can target the data attributes assigned to each component part for easy customization. ### Styling a Part To style a specific component part, target its `data-scope` and `data-part` attributes: ```css [data-scope='accordion'][data-part='item'] { border-bottom: 1px solid #e5e5e5; } ``` ### Styling a State To style a component based on its state, use the `data-state` attribute: ```css [data-scope='accordion'][data-part='item'][data-state='open'] { background-color: #f5f5f5; } ``` > **Tip:** If you prefer using classes instead of data attributes, utilize the `class` or `className` prop to add custom > classes to Ark UI components. ### Class Names If you prefer using classes instead of data attributes, utilize `class` or `className` prop to add custom classes to Ark UI components. Pass a class: ```jsx {/* … */} ``` Then use in styles: ```css .AccordionItem { border-bottom: 1px solid #e5e5e5; &[data-state='open'] { background-color: #f5f5f5; } } ``` ## Styling with Panda CSS [Panda CSS](https://panda-css.com) is a best-in-class CSS-in-JS framework that integrates seamlessly with Ark UI, providing an efficient styling solution. ### Styling a part Panda offers various ways to write styles, but in the context of Ark UI, we recommend using the `defineSlotRecipe` function to style a component with its different parts and variants. > **Important:** When importing anatomy objects, we recommend using the `@ark-ui//anatomy` entrypoint (e.g., > `@ark-ui/react/anatomy`) instead of the main package export to avoid potential build and import errors. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid #e5e5e5', }, }, defaultVariants: {}, variants: {}, }) ``` ### Styling a state To style a component based on its state, you can use built in [conditions](https://panda-css.com/docs/customization/conditions) in Panda CSS. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid {colors.gray.300}', _open: { // [!code highlight] backgroundColor: 'gray.100', }, }, }, defaultVariants: {}, variants: {}, }) ``` ## Styling with Tailwind CSS [Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework providing a flexible way to style your components. ### Styling a Part To style a part, apply classes directly to the parts using either `class` or `className`, depending on the JavaScript framework. ```jsx {/* … */} ``` ### Styling a State Leverage Tailwind CSS's variant selector to style a component based on its data-state attribute. ```jsx {/* … */} ``` # Styling (SOLID) ## Overview Ark UI is a headless component library that works with any styling solution. It provides functional styles for elements like popovers for positioning, while leaving presentation styles up to you. Some components also expose CSS variables that can be used for styling or animations. > **Tip:** Looking for a ready-to-use solution? Checkout [Park UI](https://park-ui.com) for a collection of pre-designed > styles based on Ark UI components. ### Data Attributes Ark UI components use `data-scope` and `data-part` attributes to target specific elements within a component. Interactive components often include `data-*` attributes to indicate their state. For example, here's what an open accordion item looks like: ```html
                    ``` For more details on each component's data attributes, refer to their respective documentation. ## Styling with CSS When styling components with CSS, you can target the data attributes assigned to each component part for easy customization. ### Styling a Part To style a specific component part, target its `data-scope` and `data-part` attributes: ```css [data-scope='accordion'][data-part='item'] { border-bottom: 1px solid #e5e5e5; } ``` ### Styling a State To style a component based on its state, use the `data-state` attribute: ```css [data-scope='accordion'][data-part='item'][data-state='open'] { background-color: #f5f5f5; } ``` > **Tip:** If you prefer using classes instead of data attributes, utilize the `class` or `className` prop to add custom > classes to Ark UI components. ### Class Names If you prefer using classes instead of data attributes, utilize `class` or `className` prop to add custom classes to Ark UI components. Pass a class: ```jsx {/* … */} ``` Then use in styles: ```css .AccordionItem { border-bottom: 1px solid #e5e5e5; &[data-state='open'] { background-color: #f5f5f5; } } ``` ## Styling with Panda CSS [Panda CSS](https://panda-css.com) is a best-in-class CSS-in-JS framework that integrates seamlessly with Ark UI, providing an efficient styling solution. ### Styling a part Panda offers various ways to write styles, but in the context of Ark UI, we recommend using the `defineSlotRecipe` function to style a component with its different parts and variants. > **Important:** When importing anatomy objects, we recommend using the `@ark-ui//anatomy` entrypoint (e.g., > `@ark-ui/react/anatomy`) instead of the main package export to avoid potential build and import errors. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid #e5e5e5', }, }, defaultVariants: {}, variants: {}, }) ``` ### Styling a state To style a component based on its state, you can use built in [conditions](https://panda-css.com/docs/customization/conditions) in Panda CSS. ```ts import { accordionAnatomy } from '@ark-ui/react/anatomy' import { defineSlotRecipe } from '@pandacss/dev' export const accordionStyles = defineSlotRecipe({ className: 'accordion', slots: accordionAnatomy.keys(), base: { item: { borderBottom: '1px solid {colors.gray.300}', _open: { // [!code highlight] backgroundColor: 'gray.100', }, }, }, defaultVariants: {}, variants: {}, }) ``` ## Styling with Tailwind CSS [Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework providing a flexible way to style your components. ### Styling a Part To style a part, apply classes directly to the parts using either `class` or `className`, depending on the JavaScript framework. ```jsx {/* … */} ``` ### Styling a State Leverage Tailwind CSS's variant selector to style a component based on its data-state attribute. ```jsx {/* … */} ``` # Composition (REACT) ## The asChild Prop In Ark UI, the `asChild` prop lets you integrate custom components, ensuring consistent styling and behavior while promoting flexibility and reusability. All Ark components that render a DOM element accept the `asChild` prop. Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`: In this example, the `asChild` prop allows the `Button` to be used as the trigger for the `Popover`, inheriting its behaviors from Popover.Trigger. ## The Ark Factory You can use the `ark` factory to create your own elements that work just like Ark UI components. This will produce the following HTML: ```html Ark UI ``` ## ID Composition When composing components that need to work together, share IDs between them using the `ids` prop for proper accessibility and interaction. ```tsx import { Avatar } from '@ark-ui/react/avatar' import { Tooltip } from '@ark-ui/react/tooltip' import { useId } from 'react' export const TooltipWithAvatar = () => { const id = useId() return ( SA Segun Adebayo is online ) } ``` Both components share the same `id` through their `ids` props, creating proper accessibility bindings, `aria-*` attributes and interaction behavior. ## Limitations When using the `asChild` prop, ensure you pass only a single child element. Passing multiple children may cause rendering issues. Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements. For instance, they may require a label element as a child. If you change the underlying element type, ensure it remains accessible and functional. # Composition (VUE) ## The asChild Prop In Ark UI, the `asChild` prop lets you integrate custom components, ensuring consistent styling and behavior while promoting flexibility and reusability. All Ark components that render a DOM element accept the `asChild` prop. Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`: In this example, the `asChild` prop allows the `Button` to be used as the trigger for the `Popover`, inheriting its behaviors from Popover.Trigger. ## The Ark Factory You can use the `ark` factory to create your own elements that work just like Ark UI components. This will produce the following HTML: ```html Ark UI ``` ## ID Composition When composing components that need to work together, share IDs between them using the `ids` prop for proper accessibility and interaction. ```tsx import { Avatar } from '@ark-ui/react/avatar' import { Tooltip } from '@ark-ui/react/tooltip' import { useId } from 'react' export const TooltipWithAvatar = () => { const id = useId() return ( SA Segun Adebayo is online ) } ``` Both components share the same `id` through their `ids` props, creating proper accessibility bindings, `aria-*` attributes and interaction behavior. ## Limitations When using the `asChild` prop, ensure you pass only a single child element. Passing multiple children may cause rendering issues. Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements. For instance, they may require a label element as a child. If you change the underlying element type, ensure it remains accessible and functional. # Composition (SVELTE) ## The asChild Prop In Ark UI, the `asChild` prop lets you integrate custom components, ensuring consistent styling and behavior while promoting flexibility and reusability. All Ark components that render a DOM element accept the `asChild` prop. Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`: In this example, the `asChild` prop allows the `Button` to be used as the trigger for the `Popover`, inheriting its behaviors from Popover.Trigger. ## The Ark Factory You can use the `ark` factory to create your own elements that work just like Ark UI components. This will produce the following HTML: ```html Ark UI ``` ## ID Composition When composing components that need to work together, share IDs between them using the `ids` prop for proper accessibility and interaction. ```tsx import { Avatar } from '@ark-ui/react/avatar' import { Tooltip } from '@ark-ui/react/tooltip' import { useId } from 'react' export const TooltipWithAvatar = () => { const id = useId() return ( SA Segun Adebayo is online ) } ``` Both components share the same `id` through their `ids` props, creating proper accessibility bindings, `aria-*` attributes and interaction behavior. ## Limitations When using the `asChild` prop, ensure you pass only a single child element. Passing multiple children may cause rendering issues. Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements. For instance, they may require a label element as a child. If you change the underlying element type, ensure it remains accessible and functional. # Composition (SOLID) ## The asChild Prop In Ark UI, the `asChild` prop lets you integrate custom components, ensuring consistent styling and behavior while promoting flexibility and reusability. All Ark components that render a DOM element accept the `asChild` prop. Here's an example using `asChild` to integrate a custom `Button` component within a `Popover`: In this example, the `asChild` prop allows the `Button` to be used as the trigger for the `Popover`, inheriting its behaviors from Popover.Trigger. ## The Ark Factory You can use the `ark` factory to create your own elements that work just like Ark UI components. This will produce the following HTML: ```html Ark UI ``` ## ID Composition When composing components that need to work together, share IDs between them using the `ids` prop for proper accessibility and interaction. ```tsx import { Avatar } from '@ark-ui/react/avatar' import { Tooltip } from '@ark-ui/react/tooltip' import { useId } from 'react' export const TooltipWithAvatar = () => { const id = useId() return ( SA Segun Adebayo is online ) } ``` Both components share the same `id` through their `ids` props, creating proper accessibility bindings, `aria-*` attributes and interaction behavior. ## Limitations When using the `asChild` prop, ensure you pass only a single child element. Passing multiple children may cause rendering issues. Certain components, such as `Checkbox.Root` or `RadioGroup.Item`, have specific requirements for their child elements. For instance, they may require a label element as a child. If you change the underlying element type, ensure it remains accessible and functional. # Component State (REACT) Need to access a component's state? You have three options: | Approach | When to use it | | ------------------------------- | --------------------------------------------- | | `Component.Context` | Quick inline access via render props | | `use*Context` hooks | Build custom child components that read state | | `useComponent` + `RootProvider` | Control the component from outside | ## Context Components Use `Component.Context` to access state inline via render props. Here, `Avatar.Fallback` reads the `loaded` state to show different content: > **Good to know (RSC)**: The render prop pattern requires the `'use client'` directive when using React Server > Components. ## Context Hooks Every component exports a `use*Context` hook (like `useDialogContext` or `useMenuContext`). Call it from any child component to access state and methods—no render props needed. ```tsx import { Dialog, useDialogContext } from '@ark-ui/react/dialog' function CustomCloseButton() { const dialog = useDialogContext() return } export const Demo = () => ( Open ) ``` The hook returns the same API as `Component.Context`, just without the nesting. ## Provider Components Need to control a component from outside its tree? Use a `useComponent` hook (like `useDialog`) with `RootProvider`. > When you use `RootProvider`, skip the `Root` component—you don't need both. ## Choosing the Right Approach - **`Component.Context`** — Quick inline access for conditional rendering - **`use*Context` hooks** — Build reusable child components that need parent state - **`useComponent` + `RootProvider`** — Trigger actions from outside (like opening a dialog from a menu item) # Component State (VUE) Need to access a component's state? You have three options: | Approach | When to use it | | ------------------------------- | --------------------------------------------- | | `Component.Context` | Quick inline access via render props | | `use*Context` hooks | Build custom child components that read state | | `useComponent` + `RootProvider` | Control the component from outside | ## Context Components Use `Component.Context` to access state inline via render props. Here, `Avatar.Fallback` reads the `loaded` state to show different content: > **Good to know (RSC)**: The render prop pattern requires the `'use client'` directive when using React Server > Components. ## Context Hooks Every component exports a `use*Context` hook (like `useDialogContext` or `useMenuContext`). Call it from any child component to access state and methods—no render props needed. ```tsx import { Dialog, useDialogContext } from '@ark-ui/react/dialog' function CustomCloseButton() { const dialog = useDialogContext() return } export const Demo = () => ( Open ) ``` The hook returns the same API as `Component.Context`, just without the nesting. ## Provider Components Need to control a component from outside its tree? Use a `useComponent` hook (like `useDialog`) with `RootProvider`. > When you use `RootProvider`, skip the `Root` component—you don't need both. ## Choosing the Right Approach - **`Component.Context`** — Quick inline access for conditional rendering - **`use*Context` hooks** — Build reusable child components that need parent state - **`useComponent` + `RootProvider`** — Trigger actions from outside (like opening a dialog from a menu item) # Component State (SVELTE) Need to access a component's state? You have three options: | Approach | When to use it | | ------------------------------- | --------------------------------------------- | | `Component.Context` | Quick inline access via render props | | `use*Context` hooks | Build custom child components that read state | | `useComponent` + `RootProvider` | Control the component from outside | ## Context Components Use `Component.Context` to access state inline via render props. Here, `Avatar.Fallback` reads the `loaded` state to show different content: > **Good to know (RSC)**: The render prop pattern requires the `'use client'` directive when using React Server > Components. ## Context Hooks Every component exports a `use*Context` hook (like `useDialogContext` or `useMenuContext`). Call it from any child component to access state and methods—no render props needed. ```tsx import { Dialog, useDialogContext } from '@ark-ui/react/dialog' function CustomCloseButton() { const dialog = useDialogContext() return } export const Demo = () => ( Open ) ``` The hook returns the same API as `Component.Context`, just without the nesting. ## Provider Components Need to control a component from outside its tree? Use a `useComponent` hook (like `useDialog`) with `RootProvider`. > When you use `RootProvider`, skip the `Root` component—you don't need both. ## Choosing the Right Approach - **`Component.Context`** — Quick inline access for conditional rendering - **`use*Context` hooks** — Build reusable child components that need parent state - **`useComponent` + `RootProvider`** — Trigger actions from outside (like opening a dialog from a menu item) # Component State (SOLID) Need to access a component's state? You have three options: | Approach | When to use it | | ------------------------------- | --------------------------------------------- | | `Component.Context` | Quick inline access via render props | | `use*Context` hooks | Build custom child components that read state | | `useComponent` + `RootProvider` | Control the component from outside | ## Context Components Use `Component.Context` to access state inline via render props. Here, `Avatar.Fallback` reads the `loaded` state to show different content: > **Good to know (RSC)**: The render prop pattern requires the `'use client'` directive when using React Server > Components. ## Context Hooks Every component exports a `use*Context` hook (like `useDialogContext` or `useMenuContext`). Call it from any child component to access state and methods—no render props needed. ```tsx import { Dialog, useDialogContext } from '@ark-ui/react/dialog' function CustomCloseButton() { const dialog = useDialogContext() return } export const Demo = () => ( Open ) ``` The hook returns the same API as `Component.Context`, just without the nesting. ## Provider Components Need to control a component from outside its tree? Use a `useComponent` hook (like `useDialog`) with `RootProvider`. > When you use `RootProvider`, skip the `Root` component—you don't need both. ## Choosing the Right Approach - **`Component.Context`** — Quick inline access for conditional rendering - **`use*Context` hooks** — Build reusable child components that need parent state - **`useComponent` + `RootProvider`** — Trigger actions from outside (like opening a dialog from a menu item) # Animation (REACT) Adding animation to Ark UI Components is as straightforward as with any other component, but keep in mind some considerations when working with exit animations with JavaScript animation libraries. ## Animating with CSS The most straightforward method to animate your elements is using CSS. You can animate both the mounting and unmounting phases with CSS. The latter is achievable because Ark UI Components postpones the unmounting while your animation runs. Below is a simple example of creating a fade-in and fade-out animation using CSS keyframes: ```css @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } ``` You can use these keyframes to animate any element during its lifecycle. For instance, to apply the `fadeIn` animation when your `Tooltip` enters the 'open' state, and `fadeOut` when it enters the 'closed' state, you could use the following styles: ```css [data-scope='tooltip'][data-part='content'][data-state='open'] { animation: fadeIn 300ms ease-out; } [data-scope='tooltip'][data-part='content'][data-state='closed'] { animation: fadeOut 300ms ease-in; } ``` ## Animating with JS Libraries There's plenty of versatility when it comes to animating your Ark UI Elements with JavaScript libraries. Various libraries such as GreenSock, anime.js, Framer Motion, and more can add a new level of interaction and feedback to your UI components. One significant advantage of using Ark UI Elements is the control you have over the unmounting phase of your components. This is primarily facilitated through the `present` prop. The `present` prop allows the component to stay mounted even after its enclosing condition has been falsified, allowing for exit animations to complete before the component is removed from the DOM. # Animation (VUE) Adding animation to Ark UI Components is as straightforward as with any other component, but keep in mind some considerations when working with exit animations with JavaScript animation libraries. ## Animating with CSS The most straightforward method to animate your elements is using CSS. You can animate both the mounting and unmounting phases with CSS. The latter is achievable because Ark UI Components postpones the unmounting while your animation runs. Below is a simple example of creating a fade-in and fade-out animation using CSS keyframes: ```css @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } ``` You can use these keyframes to animate any element during its lifecycle. For instance, to apply the `fadeIn` animation when your `Tooltip` enters the 'open' state, and `fadeOut` when it enters the 'closed' state, you could use the following styles: ```css [data-scope='tooltip'][data-part='content'][data-state='open'] { animation: fadeIn 300ms ease-out; } [data-scope='tooltip'][data-part='content'][data-state='closed'] { animation: fadeOut 300ms ease-in; } ``` ## Animating with JS Libraries There's plenty of versatility when it comes to animating your Ark UI Elements with JavaScript libraries. Various libraries such as GreenSock, anime.js, Framer Motion, and more can add a new level of interaction and feedback to your UI components. One significant advantage of using Ark UI Elements is the control you have over the unmounting phase of your components. This is primarily facilitated through the `present` prop. The `present` prop allows the component to stay mounted even after its enclosing condition has been falsified, allowing for exit animations to complete before the component is removed from the DOM. # Animation (SVELTE) Adding animation to Ark UI Components is as straightforward as with any other component, but keep in mind some considerations when working with exit animations with JavaScript animation libraries. ## Animating with CSS The most straightforward method to animate your elements is using CSS. You can animate both the mounting and unmounting phases with CSS. The latter is achievable because Ark UI Components postpones the unmounting while your animation runs. Below is a simple example of creating a fade-in and fade-out animation using CSS keyframes: ```css @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } ``` You can use these keyframes to animate any element during its lifecycle. For instance, to apply the `fadeIn` animation when your `Tooltip` enters the 'open' state, and `fadeOut` when it enters the 'closed' state, you could use the following styles: ```css [data-scope='tooltip'][data-part='content'][data-state='open'] { animation: fadeIn 300ms ease-out; } [data-scope='tooltip'][data-part='content'][data-state='closed'] { animation: fadeOut 300ms ease-in; } ``` ## Animating with JS Libraries There's plenty of versatility when it comes to animating your Ark UI Elements with JavaScript libraries. Various libraries such as GreenSock, anime.js, Framer Motion, and more can add a new level of interaction and feedback to your UI components. One significant advantage of using Ark UI Elements is the control you have over the unmounting phase of your components. This is primarily facilitated through the `present` prop. The `present` prop allows the component to stay mounted even after its enclosing condition has been falsified, allowing for exit animations to complete before the component is removed from the DOM. # Animation (SOLID) Adding animation to Ark UI Components is as straightforward as with any other component, but keep in mind some considerations when working with exit animations with JavaScript animation libraries. ## Animating with CSS The most straightforward method to animate your elements is using CSS. You can animate both the mounting and unmounting phases with CSS. The latter is achievable because Ark UI Components postpones the unmounting while your animation runs. Below is a simple example of creating a fade-in and fade-out animation using CSS keyframes: ```css @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } ``` You can use these keyframes to animate any element during its lifecycle. For instance, to apply the `fadeIn` animation when your `Tooltip` enters the 'open' state, and `fadeOut` when it enters the 'closed' state, you could use the following styles: ```css [data-scope='tooltip'][data-part='content'][data-state='open'] { animation: fadeIn 300ms ease-out; } [data-scope='tooltip'][data-part='content'][data-state='closed'] { animation: fadeOut 300ms ease-in; } ``` ## Animating with JS Libraries There's plenty of versatility when it comes to animating your Ark UI Elements with JavaScript libraries. Various libraries such as GreenSock, anime.js, Framer Motion, and more can add a new level of interaction and feedback to your UI components. One significant advantage of using Ark UI Elements is the control you have over the unmounting phase of your components. This is primarily facilitated through the `present` prop. The `present` prop allows the component to stay mounted even after its enclosing condition has been falsified, allowing for exit animations to complete before the component is removed from the DOM. # Forms (REACT) Ark UI provides the `Field` and `Fieldset` components for integrating with native `form` element or popular form libraries like [React Hook Form](https://react-hook-form.com/), [TanStack Form](https://tanstack.com/form/latest), and [Vee Validate](https://vee-validate.logaretm.com). ## Field Context Form components in Ark UI automatically integrate with `Field` through context. When nested inside a `Field.Root`, they inherit `disabled`, `invalid`, `required`, and `readOnly` states automatically. ```tsx import { Field } from '@ark-ui/react/field' import { NumberInput } from '@ark-ui/react/number-input' const Demo = () => ( {/* NumberInput will be disabled */} ) ``` ### Accessible Labels When building accessible forms, you need to ensure that they are properly labeled and described. - `Field.Label`: Used to provide an accessible label the input. - `Field.HelperText`: Used to provide additional instructions about the input. These components are automatically linked to the input element via the `aria-describedby` attribute. > **Best practice**: Make sure that labels are visible (and not just used as placeholders) for screen readers to read > them. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username This will be your public display name.
                    ) ``` ### Error Handling and Validation When the input is invalid, you can use the `Field.ErrorText` component to provide an error message for the input, and pass the `invalid` prop to the `Field.Root` component. > **Best practice**: Make sure to provide clear, specific error messages that are easy to understand and fix. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username Username is required.
                    ) ``` ### Required Fields To indicate that a field is required, you can pass the `required` prop to the `Field.Root` component. Optionally, you can use the `Field.RequiredIndicator` component to indicate that the field is required. > **Best practice**: Don't rely solely on color to indicate required status ```tsx import { Field } from '@ark-ui/react/field' export const Demo = () => (
                    Username (required) Username is required.
                    ) ``` To indicate that a field is optional, use the `fallback` prop on the `Field.RequiredIndicator` component. ```tsx (required) ``` ### Native Controls Field supports native HTML form controls including `input`, `textarea`, and `select`: ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    {/* Input */} Email {/* Textarea */} Bio {/* Select */} Country
                    ) ``` ### Form Reset When the `reset` event is triggered on a form, all Ark UI components automatically sync their internal state with the form's reset values. > **Note**: For this to work correctly, always include the `HiddenInput` component in your form controls. The hidden > input participates in the native form reset mechanism, and Ark UI listens for this to sync the component state. ```tsx import { Checkbox } from '@ark-ui/react/checkbox' const Demo = () => { return (
                    I agree to the terms {/* Clicking reset will restore checkbox to defaultChecked state */}
                    ) } ``` ## Fieldset Context When you have multiple fields in a form or a component that renders multiple `input` elements, you can use the `Fieldset` component to group them together. Common use cases checkbox group, radio group, input + select composition, etc. ### Checkbox Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred frameworks ) ``` ### Radio Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { RadioGroup } from '@ark-ui/react/radio-group' import { RadioIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred framework ) ``` ## React Hook Form Ark UI integrates seamlessly with React Hook Form. Use the `register` function for simple inputs and `Controller` for complex components. ### Native Controls ```tsx import { Field } from '@ark-ui/react/field' import { useForm } from 'react-hook-form' interface FormValues { firstName: string email: string } const Demo = () => { const { register, handleSubmit, formState: { errors }, } = useForm() const onSubmit = (data: FormValues) => console.log(data) return (
                    First Name {errors.firstName?.message} Email {errors.email?.message}
                    ) } ``` ### Custom Components Use the `Controller` hook to integrate custom form components like select or combobox. > **Best practice**: To ensure `react-hook-form` moves focus to invalid field control when performing validation, > forward the field's `ref` to the respective Ark UI component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { Controller, useForm } from 'react-hook-form' const Demo = () => { const { control, handleSubmit } = useForm({ defaultValues: { framework: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    console.log(data))}> ( onChange(e.value[0])} onInteractOutside={() => onBlur()} > Framework {collection.items.map((item) => ( {item} ))} {error?.message} )} /> ) } ``` ## TanStack Form TanStack Form provides powerful form state management that works well with Ark UI. ### Native Controls ```tsx import { useForm } from '@tanstack/react-form' const form = useForm({ defaultValues: { firstName: '' }, }) const Demo = () => (
                    ( First Name field.handleChange(e.target.value)} onBlur={field.handleBlur} /> {field.state.meta.errors.join(',')} )} /> ) ``` ### Custom Components Here's an example of how to integrate custom components like the select or combobox with Tanstack's `form.Field` component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { useForm } from '@tanstack/react-form' const Demo = () => { const form = useForm({ defaultValues: { username: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    { e.preventDefault() e.stopPropagation() form.handleSubmit() }} > (value.length < 3 ? 'Username must be at least 3 characters' : undefined), }} children={(field) => ( 0}> Username field.handleChange(e.value[0])} onInteractOutside={() => field.handleBlur()} > Username {collection.items.map((item) => ( {item} ))} )} /> ) } ``` # Forms (VUE) Ark UI provides the `Field` and `Fieldset` components for integrating with native `form` element or popular form libraries like [React Hook Form](https://react-hook-form.com/), [TanStack Form](https://tanstack.com/form/latest), and [Vee Validate](https://vee-validate.logaretm.com). ## Field Context Form components in Ark UI automatically integrate with `Field` through context. When nested inside a `Field.Root`, they inherit `disabled`, `invalid`, `required`, and `readOnly` states automatically. ```tsx import { Field } from '@ark-ui/react/field' import { NumberInput } from '@ark-ui/react/number-input' const Demo = () => ( {/* NumberInput will be disabled */} ) ``` ### Accessible Labels When building accessible forms, you need to ensure that they are properly labeled and described. - `Field.Label`: Used to provide an accessible label the input. - `Field.HelperText`: Used to provide additional instructions about the input. These components are automatically linked to the input element via the `aria-describedby` attribute. > **Best practice**: Make sure that labels are visible (and not just used as placeholders) for screen readers to read > them. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username This will be your public display name.
                    ) ``` ### Error Handling and Validation When the input is invalid, you can use the `Field.ErrorText` component to provide an error message for the input, and pass the `invalid` prop to the `Field.Root` component. > **Best practice**: Make sure to provide clear, specific error messages that are easy to understand and fix. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username Username is required.
                    ) ``` ### Required Fields To indicate that a field is required, you can pass the `required` prop to the `Field.Root` component. Optionally, you can use the `Field.RequiredIndicator` component to indicate that the field is required. > **Best practice**: Don't rely solely on color to indicate required status ```tsx import { Field } from '@ark-ui/react/field' export const Demo = () => (
                    Username (required) Username is required.
                    ) ``` To indicate that a field is optional, use the `fallback` prop on the `Field.RequiredIndicator` component. ```tsx (required) ``` ### Native Controls Field supports native HTML form controls including `input`, `textarea`, and `select`: ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    {/* Input */} Email {/* Textarea */} Bio {/* Select */} Country
                    ) ``` ### Form Reset When the `reset` event is triggered on a form, all Ark UI components automatically sync their internal state with the form's reset values. > **Note**: For this to work correctly, always include the `HiddenInput` component in your form controls. The hidden > input participates in the native form reset mechanism, and Ark UI listens for this to sync the component state. ```tsx import { Checkbox } from '@ark-ui/react/checkbox' const Demo = () => { return (
                    I agree to the terms {/* Clicking reset will restore checkbox to defaultChecked state */}
                    ) } ``` ## Fieldset Context When you have multiple fields in a form or a component that renders multiple `input` elements, you can use the `Fieldset` component to group them together. Common use cases checkbox group, radio group, input + select composition, etc. ### Checkbox Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred frameworks ) ``` ### Radio Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { RadioGroup } from '@ark-ui/react/radio-group' import { RadioIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred framework ) ``` ## React Hook Form Ark UI integrates seamlessly with React Hook Form. Use the `register` function for simple inputs and `Controller` for complex components. ### Native Controls ```tsx import { Field } from '@ark-ui/react/field' import { useForm } from 'react-hook-form' interface FormValues { firstName: string email: string } const Demo = () => { const { register, handleSubmit, formState: { errors }, } = useForm() const onSubmit = (data: FormValues) => console.log(data) return (
                    First Name {errors.firstName?.message} Email {errors.email?.message}
                    ) } ``` ### Custom Components Use the `Controller` hook to integrate custom form components like select or combobox. > **Best practice**: To ensure `react-hook-form` moves focus to invalid field control when performing validation, > forward the field's `ref` to the respective Ark UI component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { Controller, useForm } from 'react-hook-form' const Demo = () => { const { control, handleSubmit } = useForm({ defaultValues: { framework: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    console.log(data))}> ( onChange(e.value[0])} onInteractOutside={() => onBlur()} > Framework {collection.items.map((item) => ( {item} ))} {error?.message} )} /> ) } ``` ## TanStack Form TanStack Form provides powerful form state management that works well with Ark UI. ### Native Controls ```tsx import { useForm } from '@tanstack/react-form' const form = useForm({ defaultValues: { firstName: '' }, }) const Demo = () => (
                    ( First Name field.handleChange(e.target.value)} onBlur={field.handleBlur} /> {field.state.meta.errors.join(',')} )} /> ) ``` ### Custom Components Here's an example of how to integrate custom components like the select or combobox with Tanstack's `form.Field` component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { useForm } from '@tanstack/react-form' const Demo = () => { const form = useForm({ defaultValues: { username: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    { e.preventDefault() e.stopPropagation() form.handleSubmit() }} > (value.length < 3 ? 'Username must be at least 3 characters' : undefined), }} children={(field) => ( 0}> Username field.handleChange(e.value[0])} onInteractOutside={() => field.handleBlur()} > Username {collection.items.map((item) => ( {item} ))} )} /> ) } ``` # Forms (SVELTE) Ark UI provides the `Field` and `Fieldset` components for integrating with native `form` element or popular form libraries like [React Hook Form](https://react-hook-form.com/), [TanStack Form](https://tanstack.com/form/latest), and [Vee Validate](https://vee-validate.logaretm.com). ## Field Context Form components in Ark UI automatically integrate with `Field` through context. When nested inside a `Field.Root`, they inherit `disabled`, `invalid`, `required`, and `readOnly` states automatically. ```tsx import { Field } from '@ark-ui/react/field' import { NumberInput } from '@ark-ui/react/number-input' const Demo = () => ( {/* NumberInput will be disabled */} ) ``` ### Accessible Labels When building accessible forms, you need to ensure that they are properly labeled and described. - `Field.Label`: Used to provide an accessible label the input. - `Field.HelperText`: Used to provide additional instructions about the input. These components are automatically linked to the input element via the `aria-describedby` attribute. > **Best practice**: Make sure that labels are visible (and not just used as placeholders) for screen readers to read > them. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username This will be your public display name.
                    ) ``` ### Error Handling and Validation When the input is invalid, you can use the `Field.ErrorText` component to provide an error message for the input, and pass the `invalid` prop to the `Field.Root` component. > **Best practice**: Make sure to provide clear, specific error messages that are easy to understand and fix. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username Username is required.
                    ) ``` ### Required Fields To indicate that a field is required, you can pass the `required` prop to the `Field.Root` component. Optionally, you can use the `Field.RequiredIndicator` component to indicate that the field is required. > **Best practice**: Don't rely solely on color to indicate required status ```tsx import { Field } from '@ark-ui/react/field' export const Demo = () => (
                    Username (required) Username is required.
                    ) ``` To indicate that a field is optional, use the `fallback` prop on the `Field.RequiredIndicator` component. ```tsx (required) ``` ### Native Controls Field supports native HTML form controls including `input`, `textarea`, and `select`: ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    {/* Input */} Email {/* Textarea */} Bio {/* Select */} Country
                    ) ``` ### Form Reset When the `reset` event is triggered on a form, all Ark UI components automatically sync their internal state with the form's reset values. > **Note**: For this to work correctly, always include the `HiddenInput` component in your form controls. The hidden > input participates in the native form reset mechanism, and Ark UI listens for this to sync the component state. ```tsx import { Checkbox } from '@ark-ui/react/checkbox' const Demo = () => { return (
                    I agree to the terms {/* Clicking reset will restore checkbox to defaultChecked state */}
                    ) } ``` ## Fieldset Context When you have multiple fields in a form or a component that renders multiple `input` elements, you can use the `Fieldset` component to group them together. Common use cases checkbox group, radio group, input + select composition, etc. ### Checkbox Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred frameworks ) ``` ### Radio Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { RadioGroup } from '@ark-ui/react/radio-group' import { RadioIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred framework ) ``` ## React Hook Form Ark UI integrates seamlessly with React Hook Form. Use the `register` function for simple inputs and `Controller` for complex components. ### Native Controls ```tsx import { Field } from '@ark-ui/react/field' import { useForm } from 'react-hook-form' interface FormValues { firstName: string email: string } const Demo = () => { const { register, handleSubmit, formState: { errors }, } = useForm() const onSubmit = (data: FormValues) => console.log(data) return (
                    First Name {errors.firstName?.message} Email {errors.email?.message}
                    ) } ``` ### Custom Components Use the `Controller` hook to integrate custom form components like select or combobox. > **Best practice**: To ensure `react-hook-form` moves focus to invalid field control when performing validation, > forward the field's `ref` to the respective Ark UI component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { Controller, useForm } from 'react-hook-form' const Demo = () => { const { control, handleSubmit } = useForm({ defaultValues: { framework: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    console.log(data))}> ( onChange(e.value[0])} onInteractOutside={() => onBlur()} > Framework {collection.items.map((item) => ( {item} ))} {error?.message} )} /> ) } ``` ## TanStack Form TanStack Form provides powerful form state management that works well with Ark UI. ### Native Controls ```tsx import { useForm } from '@tanstack/react-form' const form = useForm({ defaultValues: { firstName: '' }, }) const Demo = () => (
                    ( First Name field.handleChange(e.target.value)} onBlur={field.handleBlur} /> {field.state.meta.errors.join(',')} )} /> ) ``` ### Custom Components Here's an example of how to integrate custom components like the select or combobox with Tanstack's `form.Field` component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { useForm } from '@tanstack/react-form' const Demo = () => { const form = useForm({ defaultValues: { username: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    { e.preventDefault() e.stopPropagation() form.handleSubmit() }} > (value.length < 3 ? 'Username must be at least 3 characters' : undefined), }} children={(field) => ( 0}> Username field.handleChange(e.value[0])} onInteractOutside={() => field.handleBlur()} > Username {collection.items.map((item) => ( {item} ))} )} /> ) } ``` # Forms (SOLID) Ark UI provides the `Field` and `Fieldset` components for integrating with native `form` element or popular form libraries like [React Hook Form](https://react-hook-form.com/), [TanStack Form](https://tanstack.com/form/latest), and [Vee Validate](https://vee-validate.logaretm.com). ## Field Context Form components in Ark UI automatically integrate with `Field` through context. When nested inside a `Field.Root`, they inherit `disabled`, `invalid`, `required`, and `readOnly` states automatically. ```tsx import { Field } from '@ark-ui/react/field' import { NumberInput } from '@ark-ui/react/number-input' const Demo = () => ( {/* NumberInput will be disabled */} ) ``` ### Accessible Labels When building accessible forms, you need to ensure that they are properly labeled and described. - `Field.Label`: Used to provide an accessible label the input. - `Field.HelperText`: Used to provide additional instructions about the input. These components are automatically linked to the input element via the `aria-describedby` attribute. > **Best practice**: Make sure that labels are visible (and not just used as placeholders) for screen readers to read > them. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username This will be your public display name.
                    ) ``` ### Error Handling and Validation When the input is invalid, you can use the `Field.ErrorText` component to provide an error message for the input, and pass the `invalid` prop to the `Field.Root` component. > **Best practice**: Make sure to provide clear, specific error messages that are easy to understand and fix. ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    Username Username is required.
                    ) ``` ### Required Fields To indicate that a field is required, you can pass the `required` prop to the `Field.Root` component. Optionally, you can use the `Field.RequiredIndicator` component to indicate that the field is required. > **Best practice**: Don't rely solely on color to indicate required status ```tsx import { Field } from '@ark-ui/react/field' export const Demo = () => (
                    Username (required) Username is required.
                    ) ``` To indicate that a field is optional, use the `fallback` prop on the `Field.RequiredIndicator` component. ```tsx (required) ``` ### Native Controls Field supports native HTML form controls including `input`, `textarea`, and `select`: ```tsx import { Field } from '@ark-ui/react/field' const Demo = () => (
                    {/* Input */} Email {/* Textarea */} Bio {/* Select */} Country
                    ) ``` ### Form Reset When the `reset` event is triggered on a form, all Ark UI components automatically sync their internal state with the form's reset values. > **Note**: For this to work correctly, always include the `HiddenInput` component in your form controls. The hidden > input participates in the native form reset mechanism, and Ark UI listens for this to sync the component state. ```tsx import { Checkbox } from '@ark-ui/react/checkbox' const Demo = () => { return (
                    I agree to the terms {/* Clicking reset will restore checkbox to defaultChecked state */}
                    ) } ``` ## Fieldset Context When you have multiple fields in a form or a component that renders multiple `input` elements, you can use the `Fieldset` component to group them together. Common use cases checkbox group, radio group, input + select composition, etc. ### Checkbox Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred frameworks ) ``` ### Radio Group ```tsx import { Fieldset } from '@ark-ui/react/fieldset' import { RadioGroup } from '@ark-ui/react/radio-group' import { RadioIcon } from 'lucide-react' const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, { label: 'Svelte', value: 'svelte' }, ] const Demo = () => ( Frameworks {items.map((item) => ( ))} Choose your preferred framework ) ``` ## React Hook Form Ark UI integrates seamlessly with React Hook Form. Use the `register` function for simple inputs and `Controller` for complex components. ### Native Controls ```tsx import { Field } from '@ark-ui/react/field' import { useForm } from 'react-hook-form' interface FormValues { firstName: string email: string } const Demo = () => { const { register, handleSubmit, formState: { errors }, } = useForm() const onSubmit = (data: FormValues) => console.log(data) return (
                    First Name {errors.firstName?.message} Email {errors.email?.message}
                    ) } ``` ### Custom Components Use the `Controller` hook to integrate custom form components like select or combobox. > **Best practice**: To ensure `react-hook-form` moves focus to invalid field control when performing validation, > forward the field's `ref` to the respective Ark UI component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { Controller, useForm } from 'react-hook-form' const Demo = () => { const { control, handleSubmit } = useForm({ defaultValues: { framework: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    console.log(data))}> ( onChange(e.value[0])} onInteractOutside={() => onBlur()} > Framework {collection.items.map((item) => ( {item} ))} {error?.message} )} /> ) } ``` ## TanStack Form TanStack Form provides powerful form state management that works well with Ark UI. ### Native Controls ```tsx import { useForm } from '@tanstack/react-form' const form = useForm({ defaultValues: { firstName: '' }, }) const Demo = () => (
                    ( First Name field.handleChange(e.target.value)} onBlur={field.handleBlur} /> {field.state.meta.errors.join(',')} )} /> ) ``` ### Custom Components Here's an example of how to integrate custom components like the select or combobox with Tanstack's `form.Field` component. ```tsx import { Field } from '@ark-ui/react/field' import { Select, createListCollection } from '@ark-ui/react/select' import { useForm } from '@tanstack/react-form' const Demo = () => { const form = useForm({ defaultValues: { username: '' }, }) const collection = createListCollection({ items: ['React', 'Solid', 'Vue', 'Svelte'], }) return (
                    { e.preventDefault() e.stopPropagation() form.handleSubmit() }} > (value.length < 3 ? 'Username must be at least 3 characters' : undefined), }} children={(field) => ( 0}> Username field.handleChange(e.value[0])} onInteractOutside={() => field.handleBlur()} > Username {collection.items.map((item) => ( {item} ))} )} /> ) } ``` # Refs (REACT) ## React In React, the `ref` prop can be used to access the rendered element. Use the `useRef` hook to create a reference and pass it to the component. ```tsx import { Slider } from '@ark-ui/react/slider' import { useRef } from 'react' export const MySlider = () => { const rootRef = useRef(null) return {/* ... */} } ``` ## Solid In Solid, the `ref` prop can be used to access the rendered element. ```tsx import { Slider } from '@ark-ui/solid/slider' export const MySlider = () => { let rootRef!: HTMLDivElement return (rootRef = el)}>{/* ... */} } ``` Alternatively, you can assign refs to Solid.js signals via the `createSignal` function. ```tsx import { Slider } from '@ark-ui/solid/slider' import { createSignal } from 'solid-js' export const MySlider = () => { const [rootRef, setRootRef] = createSignal(null) return {/* ... */} } ``` ## Vue In Vue, pass the `ref` prop to the component to access the rendered element via the `$el` property. ```vue ``` ## Svelte In Svelte 5, use the `bind:ref` directive to access the rendered element. ```svelte {/* ... */} ``` # Refs (VUE) ## React In React, the `ref` prop can be used to access the rendered element. Use the `useRef` hook to create a reference and pass it to the component. ```tsx import { Slider } from '@ark-ui/react/slider' import { useRef } from 'react' export const MySlider = () => { const rootRef = useRef(null) return {/* ... */} } ``` ## Solid In Solid, the `ref` prop can be used to access the rendered element. ```tsx import { Slider } from '@ark-ui/solid/slider' export const MySlider = () => { let rootRef!: HTMLDivElement return (rootRef = el)}>{/* ... */} } ``` Alternatively, you can assign refs to Solid.js signals via the `createSignal` function. ```tsx import { Slider } from '@ark-ui/solid/slider' import { createSignal } from 'solid-js' export const MySlider = () => { const [rootRef, setRootRef] = createSignal(null) return {/* ... */} } ``` ## Vue In Vue, pass the `ref` prop to the component to access the rendered element via the `$el` property. ```vue ``` ## Svelte In Svelte 5, use the `bind:ref` directive to access the rendered element. ```svelte {/* ... */} ``` # Refs (SVELTE) ## React In React, the `ref` prop can be used to access the rendered element. Use the `useRef` hook to create a reference and pass it to the component. ```tsx import { Slider } from '@ark-ui/react/slider' import { useRef } from 'react' export const MySlider = () => { const rootRef = useRef(null) return {/* ... */} } ``` ## Solid In Solid, the `ref` prop can be used to access the rendered element. ```tsx import { Slider } from '@ark-ui/solid/slider' export const MySlider = () => { let rootRef!: HTMLDivElement return (rootRef = el)}>{/* ... */} } ``` Alternatively, you can assign refs to Solid.js signals via the `createSignal` function. ```tsx import { Slider } from '@ark-ui/solid/slider' import { createSignal } from 'solid-js' export const MySlider = () => { const [rootRef, setRootRef] = createSignal(null) return {/* ... */} } ``` ## Vue In Vue, pass the `ref` prop to the component to access the rendered element via the `$el` property. ```vue ``` ## Svelte In Svelte 5, use the `bind:ref` directive to access the rendered element. ```svelte {/* ... */} ``` # Refs (SOLID) ## React In React, the `ref` prop can be used to access the rendered element. Use the `useRef` hook to create a reference and pass it to the component. ```tsx import { Slider } from '@ark-ui/react/slider' import { useRef } from 'react' export const MySlider = () => { const rootRef = useRef(null) return {/* ... */} } ``` ## Solid In Solid, the `ref` prop can be used to access the rendered element. ```tsx import { Slider } from '@ark-ui/solid/slider' export const MySlider = () => { let rootRef!: HTMLDivElement return (rootRef = el)}>{/* ... */} } ``` Alternatively, you can assign refs to Solid.js signals via the `createSignal` function. ```tsx import { Slider } from '@ark-ui/solid/slider' import { createSignal } from 'solid-js' export const MySlider = () => { const [rootRef, setRootRef] = createSignal(null) return {/* ... */} } ``` ## Vue In Vue, pass the `ref` prop to the component to access the rendered element via the `$el` property. ```vue ``` ## Svelte In Svelte 5, use the `bind:ref` directive to access the rendered element. ```svelte {/* ... */} ``` # AI FOR AGENTS --- # MCP Server (REACT) The Ark UI MCP Server is a specialized [Model Context Protocol](https://modelcontextprotocol.io/introduction) server that empowers AI agents to build design system components with full knowledge of Ark UI. Ark UI MCP Server It works with tools like Claude Code, Cursor, and Copilot to generate code and apply design system logic consistently across React, Vue, Solid, and Svelte. ## Tools The Ark UI MCP exposes the following tools to AI agents: - **`list_components`**: Returns a full list of all available components - **`list_examples`**: Lists various component examples - **`get_example`**: Retrieves code examples and usage patterns - **`styling_guide`**: Provides styling guidelines for components (data attributes and CSS variables) ## Setup The MCP server currently supports only [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) and is published at `@ark-ui/mcp`. ### Visual Studio Code > Make sure you have the [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) and > [GitHub Copilot Chat](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat) extensions installed. - In the `.vscode/mcp.json` file at the root of your project, add the MCP server block: ```json title=".vscode/mcp.json" { "servers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - The MCP server is now ready to use. Click the **"Start"** button in the `mcp.json` file. - Start a new chat VSCode Copilot like _"Build me a checkbox with ark ui"_ ### Cursor - In the `.cursor/mcp.json` file at the root of your project, add the following configuration: ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Go to **Settings** > **Cursor Settings** > **MCP & Integrations** and enable the Ark UI server. - Start a new chat Cursor chat like _"Build me a checkbox with ark ui"_ ### Claude Code > Make sure you have Claude Code installed. Visit [Anthropic docs](https://docs.anthropic.com/en/docs/claude-code/mcp) > for installation instructions. - Run the following command in your terminal to add the Ark UI MCP server: ```bash claude mcp add ark-ui -- npx -y @ark-ui/mcp ``` - Start a Claude Code session by running `claude` - Type a prompt like _"Build me a checkbox with ark ui"_ ### Windsurf - Navigate to **Settings** > **Windsurf Settings** > **Cascade** - Click the **Manage MCPs** button, then click the **"View raw config"** button. - Add the following to the MCP configuration file: ```json title=".codeium/windsurf/mcp_config.json" { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` > You might need to click the **Refresh** button to see the MCP server in the list. - Start a new chat Windsurf like _"Build me a checkbox with ark ui"_ ### Zed - Go to **Settings** > **Open Settings** - In the `settings.json` file, add MCP server as a new **context server**: ```json title=".config/zed/settings.json" { "context_servers": { "ark-ui": { "source": "custom", "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Start a new chat Zed like _"Build me a checkbox with ark ui"_ ### Custom MCP Client To run the MCP server in a local or development environment using a custom MCP client, you need to add the MCP server to the client's configuration file. ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` # MCP Server (VUE) The Ark UI MCP Server is a specialized [Model Context Protocol](https://modelcontextprotocol.io/introduction) server that empowers AI agents to build design system components with full knowledge of Ark UI. Ark UI MCP Server It works with tools like Claude Code, Cursor, and Copilot to generate code and apply design system logic consistently across React, Vue, Solid, and Svelte. ## Tools The Ark UI MCP exposes the following tools to AI agents: - **`list_components`**: Returns a full list of all available components - **`list_examples`**: Lists various component examples - **`get_example`**: Retrieves code examples and usage patterns - **`styling_guide`**: Provides styling guidelines for components (data attributes and CSS variables) ## Setup The MCP server currently supports only [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) and is published at `@ark-ui/mcp`. ### Visual Studio Code > Make sure you have the [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) and > [GitHub Copilot Chat](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat) extensions installed. - In the `.vscode/mcp.json` file at the root of your project, add the MCP server block: ```json title=".vscode/mcp.json" { "servers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - The MCP server is now ready to use. Click the **"Start"** button in the `mcp.json` file. - Start a new chat VSCode Copilot like _"Build me a checkbox with ark ui"_ ### Cursor - In the `.cursor/mcp.json` file at the root of your project, add the following configuration: ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Go to **Settings** > **Cursor Settings** > **MCP & Integrations** and enable the Ark UI server. - Start a new chat Cursor chat like _"Build me a checkbox with ark ui"_ ### Claude Code > Make sure you have Claude Code installed. Visit [Anthropic docs](https://docs.anthropic.com/en/docs/claude-code/mcp) > for installation instructions. - Run the following command in your terminal to add the Ark UI MCP server: ```bash claude mcp add ark-ui -- npx -y @ark-ui/mcp ``` - Start a Claude Code session by running `claude` - Type a prompt like _"Build me a checkbox with ark ui"_ ### Windsurf - Navigate to **Settings** > **Windsurf Settings** > **Cascade** - Click the **Manage MCPs** button, then click the **"View raw config"** button. - Add the following to the MCP configuration file: ```json title=".codeium/windsurf/mcp_config.json" { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` > You might need to click the **Refresh** button to see the MCP server in the list. - Start a new chat Windsurf like _"Build me a checkbox with ark ui"_ ### Zed - Go to **Settings** > **Open Settings** - In the `settings.json` file, add MCP server as a new **context server**: ```json title=".config/zed/settings.json" { "context_servers": { "ark-ui": { "source": "custom", "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Start a new chat Zed like _"Build me a checkbox with ark ui"_ ### Custom MCP Client To run the MCP server in a local or development environment using a custom MCP client, you need to add the MCP server to the client's configuration file. ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` # MCP Server (SVELTE) The Ark UI MCP Server is a specialized [Model Context Protocol](https://modelcontextprotocol.io/introduction) server that empowers AI agents to build design system components with full knowledge of Ark UI. Ark UI MCP Server It works with tools like Claude Code, Cursor, and Copilot to generate code and apply design system logic consistently across React, Vue, Solid, and Svelte. ## Tools The Ark UI MCP exposes the following tools to AI agents: - **`list_components`**: Returns a full list of all available components - **`list_examples`**: Lists various component examples - **`get_example`**: Retrieves code examples and usage patterns - **`styling_guide`**: Provides styling guidelines for components (data attributes and CSS variables) ## Setup The MCP server currently supports only [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) and is published at `@ark-ui/mcp`. ### Visual Studio Code > Make sure you have the [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) and > [GitHub Copilot Chat](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat) extensions installed. - In the `.vscode/mcp.json` file at the root of your project, add the MCP server block: ```json title=".vscode/mcp.json" { "servers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - The MCP server is now ready to use. Click the **"Start"** button in the `mcp.json` file. - Start a new chat VSCode Copilot like _"Build me a checkbox with ark ui"_ ### Cursor - In the `.cursor/mcp.json` file at the root of your project, add the following configuration: ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Go to **Settings** > **Cursor Settings** > **MCP & Integrations** and enable the Ark UI server. - Start a new chat Cursor chat like _"Build me a checkbox with ark ui"_ ### Claude Code > Make sure you have Claude Code installed. Visit [Anthropic docs](https://docs.anthropic.com/en/docs/claude-code/mcp) > for installation instructions. - Run the following command in your terminal to add the Ark UI MCP server: ```bash claude mcp add ark-ui -- npx -y @ark-ui/mcp ``` - Start a Claude Code session by running `claude` - Type a prompt like _"Build me a checkbox with ark ui"_ ### Windsurf - Navigate to **Settings** > **Windsurf Settings** > **Cascade** - Click the **Manage MCPs** button, then click the **"View raw config"** button. - Add the following to the MCP configuration file: ```json title=".codeium/windsurf/mcp_config.json" { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` > You might need to click the **Refresh** button to see the MCP server in the list. - Start a new chat Windsurf like _"Build me a checkbox with ark ui"_ ### Zed - Go to **Settings** > **Open Settings** - In the `settings.json` file, add MCP server as a new **context server**: ```json title=".config/zed/settings.json" { "context_servers": { "ark-ui": { "source": "custom", "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Start a new chat Zed like _"Build me a checkbox with ark ui"_ ### Custom MCP Client To run the MCP server in a local or development environment using a custom MCP client, you need to add the MCP server to the client's configuration file. ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` # MCP Server (SOLID) The Ark UI MCP Server is a specialized [Model Context Protocol](https://modelcontextprotocol.io/introduction) server that empowers AI agents to build design system components with full knowledge of Ark UI. Ark UI MCP Server It works with tools like Claude Code, Cursor, and Copilot to generate code and apply design system logic consistently across React, Vue, Solid, and Svelte. ## Tools The Ark UI MCP exposes the following tools to AI agents: - **`list_components`**: Returns a full list of all available components - **`list_examples`**: Lists various component examples - **`get_example`**: Retrieves code examples and usage patterns - **`styling_guide`**: Provides styling guidelines for components (data attributes and CSS variables) ## Setup The MCP server currently supports only [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) and is published at `@ark-ui/mcp`. ### Visual Studio Code > Make sure you have the [GitHub Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot) and > [GitHub Copilot Chat](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat) extensions installed. - In the `.vscode/mcp.json` file at the root of your project, add the MCP server block: ```json title=".vscode/mcp.json" { "servers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - The MCP server is now ready to use. Click the **"Start"** button in the `mcp.json` file. - Start a new chat VSCode Copilot like _"Build me a checkbox with ark ui"_ ### Cursor - In the `.cursor/mcp.json` file at the root of your project, add the following configuration: ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Go to **Settings** > **Cursor Settings** > **MCP & Integrations** and enable the Ark UI server. - Start a new chat Cursor chat like _"Build me a checkbox with ark ui"_ ### Claude Code > Make sure you have Claude Code installed. Visit [Anthropic docs](https://docs.anthropic.com/en/docs/claude-code/mcp) > for installation instructions. - Run the following command in your terminal to add the Ark UI MCP server: ```bash claude mcp add ark-ui -- npx -y @ark-ui/mcp ``` - Start a Claude Code session by running `claude` - Type a prompt like _"Build me a checkbox with ark ui"_ ### Windsurf - Navigate to **Settings** > **Windsurf Settings** > **Cascade** - Click the **Manage MCPs** button, then click the **"View raw config"** button. - Add the following to the MCP configuration file: ```json title=".codeium/windsurf/mcp_config.json" { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` > You might need to click the **Refresh** button to see the MCP server in the list. - Start a new chat Windsurf like _"Build me a checkbox with ark ui"_ ### Zed - Go to **Settings** > **Open Settings** - In the `settings.json` file, add MCP server as a new **context server**: ```json title=".config/zed/settings.json" { "context_servers": { "ark-ui": { "source": "custom", "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` - Start a new chat Zed like _"Build me a checkbox with ark ui"_ ### Custom MCP Client To run the MCP server in a local or development environment using a custom MCP client, you need to add the MCP server to the client's configuration file. ```json { "mcpServers": { "ark-ui": { "command": "npx", "args": ["-y", "@ark-ui/mcp"] } } } ``` # LLMs.txt (REACT) ## What is LLMs.txt? We support [LLMs.txt](https://llmstxt.org/) files for making the Ark UI documentation available to large language models (LLMs). This feature helps AI tools better understand our component library, its APIs, and usage patterns. ## Available Routes We provide several LLMs.txt routes to help AI tools access our documentation: - [llms.txt](https://ark-ui.com/llms.txt) - Contains a structured overview of all components and their documentation links - [llms-full.txt](https://ark-ui.com/llms-full.txt) - Provides comprehensive documentation including implementation details and examples - [llms-react.txt](https://ark-ui.com/llms-react.txt) - React-specific documentation and implementation details - [llms-solid.txt](https://ark-ui.com/llms-solid.txt) - SolidJS-specific documentation and implementation details - [llms-vue.txt](https://ark-ui.com/llms-vue.txt) - Vue-specific documentation and implementation details - [llms-svelte.txt](https://ark-ui.com/llms-svelte.txt) - Svelte-specific documentation and implementation details ## Usage with AI Tools ### Cursor Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate code suggestions and documentation for Ark UI components. [Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs) ### Windstatic Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windstatic's understanding of Ark UI components. [Read more about Windstatic Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules) ### Other AI Tools Any AI tool that supports LLMs.txt can use these routes to better understand Ark UI. Simply point your tool to any of the routes above based on your framework of choice. # LLMs.txt (VUE) ## What is LLMs.txt? We support [LLMs.txt](https://llmstxt.org/) files for making the Ark UI documentation available to large language models (LLMs). This feature helps AI tools better understand our component library, its APIs, and usage patterns. ## Available Routes We provide several LLMs.txt routes to help AI tools access our documentation: - [llms.txt](https://ark-ui.com/llms.txt) - Contains a structured overview of all components and their documentation links - [llms-full.txt](https://ark-ui.com/llms-full.txt) - Provides comprehensive documentation including implementation details and examples - [llms-react.txt](https://ark-ui.com/llms-react.txt) - React-specific documentation and implementation details - [llms-solid.txt](https://ark-ui.com/llms-solid.txt) - SolidJS-specific documentation and implementation details - [llms-vue.txt](https://ark-ui.com/llms-vue.txt) - Vue-specific documentation and implementation details - [llms-svelte.txt](https://ark-ui.com/llms-svelte.txt) - Svelte-specific documentation and implementation details ## Usage with AI Tools ### Cursor Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate code suggestions and documentation for Ark UI components. [Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs) ### Windstatic Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windstatic's understanding of Ark UI components. [Read more about Windstatic Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules) ### Other AI Tools Any AI tool that supports LLMs.txt can use these routes to better understand Ark UI. Simply point your tool to any of the routes above based on your framework of choice. # LLMs.txt (SVELTE) ## What is LLMs.txt? We support [LLMs.txt](https://llmstxt.org/) files for making the Ark UI documentation available to large language models (LLMs). This feature helps AI tools better understand our component library, its APIs, and usage patterns. ## Available Routes We provide several LLMs.txt routes to help AI tools access our documentation: - [llms.txt](https://ark-ui.com/llms.txt) - Contains a structured overview of all components and their documentation links - [llms-full.txt](https://ark-ui.com/llms-full.txt) - Provides comprehensive documentation including implementation details and examples - [llms-react.txt](https://ark-ui.com/llms-react.txt) - React-specific documentation and implementation details - [llms-solid.txt](https://ark-ui.com/llms-solid.txt) - SolidJS-specific documentation and implementation details - [llms-vue.txt](https://ark-ui.com/llms-vue.txt) - Vue-specific documentation and implementation details - [llms-svelte.txt](https://ark-ui.com/llms-svelte.txt) - Svelte-specific documentation and implementation details ## Usage with AI Tools ### Cursor Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate code suggestions and documentation for Ark UI components. [Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs) ### Windstatic Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windstatic's understanding of Ark UI components. [Read more about Windstatic Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules) ### Other AI Tools Any AI tool that supports LLMs.txt can use these routes to better understand Ark UI. Simply point your tool to any of the routes above based on your framework of choice. # LLMs.txt (SOLID) ## What is LLMs.txt? We support [LLMs.txt](https://llmstxt.org/) files for making the Ark UI documentation available to large language models (LLMs). This feature helps AI tools better understand our component library, its APIs, and usage patterns. ## Available Routes We provide several LLMs.txt routes to help AI tools access our documentation: - [llms.txt](https://ark-ui.com/llms.txt) - Contains a structured overview of all components and their documentation links - [llms-full.txt](https://ark-ui.com/llms-full.txt) - Provides comprehensive documentation including implementation details and examples - [llms-react.txt](https://ark-ui.com/llms-react.txt) - React-specific documentation and implementation details - [llms-solid.txt](https://ark-ui.com/llms-solid.txt) - SolidJS-specific documentation and implementation details - [llms-vue.txt](https://ark-ui.com/llms-vue.txt) - Vue-specific documentation and implementation details - [llms-svelte.txt](https://ark-ui.com/llms-svelte.txt) - Svelte-specific documentation and implementation details ## Usage with AI Tools ### Cursor Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate code suggestions and documentation for Ark UI components. [Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs) ### Windstatic Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windstatic's understanding of Ark UI components. [Read more about Windstatic Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules) ### Other AI Tools Any AI tool that supports LLMs.txt can use these routes to better understand Ark UI. Simply point your tool to any of the routes above based on your framework of choice. # COLLECTIONS --- # List Collection (REACT) A list collection is a collection that is based on an array of items. It is created by passing an array of items to the constructor. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, ], }) console.log(collection.items) // [{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }] ``` ### Converting value to item Use the `find` or `findMany` method to convert a value to an item. ```ts const item = collection.find('banana') console.log(item) // { label: "Banana", value: "banana" } const items = collection.findMany(['apple', 'banana']) console.log(items) // [{ label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }] ``` ### Value Traversal Use the `getNextValue` or `getPreviousValue` method to get the next or previous item based on a value. ```ts const nextValue = collection.getNextValue('apple') console.log(nextValue) // banana const previousItem = collection.getPreviousValue('banana') console.log(previousItem) // apple ``` Likewise, use the `firstValue` or `lastValue` computed properties to get the first or last item. ```ts console.log(collection.firstValue) // apple console.log(collection.lastValue) // banana ``` ### Check for value existence Use the `has` method to check if a value exists in the collection. ```ts const hasValue = collection.has('apple') console.log(hasValue) // true ``` ### Working with custom objects If you are working with custom objects, you can pass a function to the `itemToString` and `itemToValue` options to specify how to convert an item to a string and a value, respectively. > By default, we look for the `label` and `value` properties in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], itemToString: (item) => item.name, itemToValue: (item) => item.id, }) ``` To mark an item as disabled, pass a function to the `isItemDisabled` option. > By default, we look for the `disabled` property in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], isItemDisabled: (item) => item.id === 2, }) ``` ### Reorder items Use the `reorder` method to reorder items by passing the starting index and the ending index of the item to be moved. ```ts const fromIndex = 1 // Banana const toIndex = 0 // Apple collection.reorder(fromIndex, toIndex) console.log(collection.items) // [{ label: "Banana", value: "banana" }, { label: "Apple", value: "apple" }] ``` # List Collection (VUE) A list collection is a collection that is based on an array of items. It is created by passing an array of items to the constructor. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, ], }) console.log(collection.items) // [{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }] ``` ### Converting value to item Use the `find` or `findMany` method to convert a value to an item. ```ts const item = collection.find('banana') console.log(item) // { label: "Banana", value: "banana" } const items = collection.findMany(['apple', 'banana']) console.log(items) // [{ label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }] ``` ### Value Traversal Use the `getNextValue` or `getPreviousValue` method to get the next or previous item based on a value. ```ts const nextValue = collection.getNextValue('apple') console.log(nextValue) // banana const previousItem = collection.getPreviousValue('banana') console.log(previousItem) // apple ``` Likewise, use the `firstValue` or `lastValue` computed properties to get the first or last item. ```ts console.log(collection.firstValue) // apple console.log(collection.lastValue) // banana ``` ### Check for value existence Use the `has` method to check if a value exists in the collection. ```ts const hasValue = collection.has('apple') console.log(hasValue) // true ``` ### Working with custom objects If you are working with custom objects, you can pass a function to the `itemToString` and `itemToValue` options to specify how to convert an item to a string and a value, respectively. > By default, we look for the `label` and `value` properties in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], itemToString: (item) => item.name, itemToValue: (item) => item.id, }) ``` To mark an item as disabled, pass a function to the `isItemDisabled` option. > By default, we look for the `disabled` property in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], isItemDisabled: (item) => item.id === 2, }) ``` ### Reorder items Use the `reorder` method to reorder items by passing the starting index and the ending index of the item to be moved. ```ts const fromIndex = 1 // Banana const toIndex = 0 // Apple collection.reorder(fromIndex, toIndex) console.log(collection.items) // [{ label: "Banana", value: "banana" }, { label: "Apple", value: "apple" }] ``` # List Collection (SVELTE) A list collection is a collection that is based on an array of items. It is created by passing an array of items to the constructor. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, ], }) console.log(collection.items) // [{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }] ``` ### Converting value to item Use the `find` or `findMany` method to convert a value to an item. ```ts const item = collection.find('banana') console.log(item) // { label: "Banana", value: "banana" } const items = collection.findMany(['apple', 'banana']) console.log(items) // [{ label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }] ``` ### Value Traversal Use the `getNextValue` or `getPreviousValue` method to get the next or previous item based on a value. ```ts const nextValue = collection.getNextValue('apple') console.log(nextValue) // banana const previousItem = collection.getPreviousValue('banana') console.log(previousItem) // apple ``` Likewise, use the `firstValue` or `lastValue` computed properties to get the first or last item. ```ts console.log(collection.firstValue) // apple console.log(collection.lastValue) // banana ``` ### Check for value existence Use the `has` method to check if a value exists in the collection. ```ts const hasValue = collection.has('apple') console.log(hasValue) // true ``` ### Working with custom objects If you are working with custom objects, you can pass a function to the `itemToString` and `itemToValue` options to specify how to convert an item to a string and a value, respectively. > By default, we look for the `label` and `value` properties in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], itemToString: (item) => item.name, itemToValue: (item) => item.id, }) ``` To mark an item as disabled, pass a function to the `isItemDisabled` option. > By default, we look for the `disabled` property in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], isItemDisabled: (item) => item.id === 2, }) ``` ### Reorder items Use the `reorder` method to reorder items by passing the starting index and the ending index of the item to be moved. ```ts const fromIndex = 1 // Banana const toIndex = 0 // Apple collection.reorder(fromIndex, toIndex) console.log(collection.items) // [{ label: "Banana", value: "banana" }, { label: "Apple", value: "apple" }] ``` # List Collection (SOLID) A list collection is a collection that is based on an array of items. It is created by passing an array of items to the constructor. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, ], }) console.log(collection.items) // [{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }] ``` ### Converting value to item Use the `find` or `findMany` method to convert a value to an item. ```ts const item = collection.find('banana') console.log(item) // { label: "Banana", value: "banana" } const items = collection.findMany(['apple', 'banana']) console.log(items) // [{ label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }] ``` ### Value Traversal Use the `getNextValue` or `getPreviousValue` method to get the next or previous item based on a value. ```ts const nextValue = collection.getNextValue('apple') console.log(nextValue) // banana const previousItem = collection.getPreviousValue('banana') console.log(previousItem) // apple ``` Likewise, use the `firstValue` or `lastValue` computed properties to get the first or last item. ```ts console.log(collection.firstValue) // apple console.log(collection.lastValue) // banana ``` ### Check for value existence Use the `has` method to check if a value exists in the collection. ```ts const hasValue = collection.has('apple') console.log(hasValue) // true ``` ### Working with custom objects If you are working with custom objects, you can pass a function to the `itemToString` and `itemToValue` options to specify how to convert an item to a string and a value, respectively. > By default, we look for the `label` and `value` properties in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], itemToString: (item) => item.name, itemToValue: (item) => item.id, }) ``` To mark an item as disabled, pass a function to the `isItemDisabled` option. > By default, we look for the `disabled` property in the item. ```ts import { createListCollection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherry' }, ], isItemDisabled: (item) => item.id === 2, }) ``` ### Reorder items Use the `reorder` method to reorder items by passing the starting index and the ending index of the item to be moved. ```ts const fromIndex = 1 // Banana const toIndex = 0 // Apple collection.reorder(fromIndex, toIndex) console.log(collection.items) // [{ label: "Banana", value: "banana" }, { label: "Apple", value: "apple" }] ``` # Tree Collection (REACT) A tree collection is designed to manage hierarchical data structures like file systems, navigation menus, or organization charts. It provides powerful methods for traversing, manipulating, and querying tree structures. ```ts import { createTreeCollection } from '@ark-ui/react/collection' const treeData = { value: 'root', label: 'Root', children: [ { value: 'folder1', label: 'Folder 1', children: [ { value: 'file1', label: 'File 1.txt' }, { value: 'file2', label: 'File 2.txt' }, ], }, { value: 'folder2', label: 'Folder 2', children: [ { value: 'subfolder1', label: 'Subfolder 1', children: [{ value: 'file3', label: 'File 3.txt' }], }, ], }, ], } const tree = createTreeCollection({ rootNode: treeData }) ``` ### Navigation Methods The tree collection provides various methods to navigate through the hierarchical structure. #### Getting First and Last Nodes ```ts const firstNode = tree.getFirstNode() console.log(firstNode?.value) // "folder1" const lastNode = tree.getLastNode() console.log(lastNode?.value) // "folder2" ``` #### Sequential Navigation Navigate to the next or previous node in the tree traversal order: ```ts const nextNode = tree.getNextNode('file1') console.log(nextNode?.value) // "file2" const previousNode = tree.getPreviousNode('file2') console.log(previousNode?.value) // "file1" ``` ### Hierarchical Relationships #### Parent and Children Get parent and descendant nodes: ```ts // Get parent node const parentNode = tree.getParentNode('file1') console.log(parentNode?.value) // "folder1" // Get all ancestor nodes const ancestors = tree.getParentNodes('file3') console.log(ancestors.map((n) => n.value)) // ["folder2", "subfolder1"] // Get all descendant nodes const descendants = tree.getDescendantNodes('folder1') console.log(descendants.map((n) => n.value)) // ["file1", "file2"] // Get descendant values only const descendantValues = tree.getDescendantValues('folder2') console.log(descendantValues) // ["subfolder1", "file3"] ``` #### Sibling Navigation Navigate between sibling nodes: ```ts // Assuming we have the index path of "file1" const indexPath = tree.getIndexPath('file1') // [0, 0] const nextSibling = tree.getNextSibling(indexPath) console.log(nextSibling?.value) // "file2" const previousSibling = tree.getPreviousSibling(indexPath) console.log(previousSibling) // undefined (no previous sibling) // Get all siblings const siblings = tree.getSiblingNodes(indexPath) console.log(siblings.map((n) => n.value)) // ["file1", "file2"] ``` ### Index Path Operations Work with index paths to identify node positions: ```ts // Get index path for a value const indexPath = tree.getIndexPath('file3') console.log(indexPath) // [1, 0, 0] // Get value from index path const value = tree.getValue([1, 0, 0]) console.log(value) // "file3" // Get full value path (all ancestors + node) const valuePath = tree.getValuePath([1, 0, 0]) console.log(valuePath) // ["folder2", "subfolder1", "file3"] // Get node at specific index path const node = tree.at([1, 0]) console.log(node?.value) // "subfolder1" ``` ### Tree Queries #### Branch and Leaf Detection ```ts // Check if a node is a branch (has children) const folder1Node = tree.findNode('folder1') const isBranch = tree.isBranchNode(folder1Node!) console.log(isBranch) // true // Get all branch values const branchValues = tree.getBranchValues() console.log(branchValues) // ["folder1", "folder2", "subfolder1"] ``` #### Tree Traversal Visit all nodes with custom logic: ```ts tree.visit({ onEnter: (node, indexPath) => { console.log(`Visiting: ${node.value} at depth ${indexPath.length}`) // Skip certain branches if (node.value === 'folder2') { return 'skip' // Skip this branch and its children } }, }) ``` #### Filtering Create a new tree with filtered nodes: ```ts // Keep only nodes that match criteria const filteredTree = tree.filter((node, indexPath) => { return node.value.includes('file') // Only keep files }) console.log(filteredTree.getValues()) // ["file1", "file2", "file3"] ``` ### Tree Manipulation #### Adding Nodes ```ts const newFile = { value: 'newfile', label: 'New File.txt' } // Insert after a specific node const indexPath = tree.getIndexPath('file1') const updatedTree = tree.insertAfter(indexPath!, [newFile]) // Insert before a specific node const updatedTree2 = tree.insertBefore(indexPath!, [newFile]) ``` #### Removing Nodes ```ts const indexPath = tree.getIndexPath('file2') const updatedTree = tree.remove([indexPath!]) console.log(updatedTree.getValues()) // file2 is removed ``` #### Moving Nodes ```ts const fromIndexPaths = [tree.getIndexPath('file1')!] const toIndexPath = tree.getIndexPath('folder2')! const updatedTree = tree.move(fromIndexPaths, toIndexPath) // file1 is now moved under folder2 ``` #### Replacing Nodes ```ts const indexPath = tree.getIndexPath('file1')! const newNode = { value: 'replacedfile', label: 'Replaced File.txt' } const updatedTree = tree.replace(indexPath, newNode) ``` ### Utility Methods #### Flattening Convert the tree to a flat structure: ```ts const flatNodes = tree.flatten() console.log(flatNodes.map((n) => ({ value: n.value, depth: n._indexPath.length }))) // [{ value: "folder1", depth: 1 }, { value: "file1", depth: 2 }, ...] ``` #### Getting All Values ```ts const allValues = tree.getValues() console.log(allValues) // ["folder1", "file1", "file2", "folder2", "subfolder1", "file3"] ``` #### Depth Calculation ```ts const depth = tree.getDepth('file3') console.log(depth) // 3 (root -> folder2 -> subfolder1 -> file3) ``` ### Working with Custom Node Types You can customize how the tree collection interprets your data: ```ts interface CustomNode { id: string name: string items?: CustomNode[] isDisabled?: boolean } const customTree = createTreeCollection({ rootNode: { id: 'root', name: 'Root', items: [ { id: '1', name: 'Item 1', isDisabled: false }, { id: '2', name: 'Item 2', isDisabled: true }, ], }, nodeToValue: (node) => node.id, nodeToString: (node) => node.name, nodeToChildren: (node) => node.items, isNodeDisabled: (node) => node.isDisabled ?? false, }) ``` ### Creating Trees from File Paths Create a tree structure from file paths: ```ts import { createFileTreeCollection } from '@ark-ui/react/collection' const paths = ['src/components/Button.tsx', 'src/components/Input.tsx', 'src/utils/helpers.ts', 'docs/README.md'] const fileTree = createFileTreeCollection(paths) console.log(fileTree.getBranchValues()) // ["src", "components", "utils", "docs"] ``` > **Good to know**: Tree collections are immutable - all modification methods return a new tree instance rather than > modifying the original. # Tree Collection (VUE) A tree collection is designed to manage hierarchical data structures like file systems, navigation menus, or organization charts. It provides powerful methods for traversing, manipulating, and querying tree structures. ```ts import { createTreeCollection } from '@ark-ui/react/collection' const treeData = { value: 'root', label: 'Root', children: [ { value: 'folder1', label: 'Folder 1', children: [ { value: 'file1', label: 'File 1.txt' }, { value: 'file2', label: 'File 2.txt' }, ], }, { value: 'folder2', label: 'Folder 2', children: [ { value: 'subfolder1', label: 'Subfolder 1', children: [{ value: 'file3', label: 'File 3.txt' }], }, ], }, ], } const tree = createTreeCollection({ rootNode: treeData }) ``` ### Navigation Methods The tree collection provides various methods to navigate through the hierarchical structure. #### Getting First and Last Nodes ```ts const firstNode = tree.getFirstNode() console.log(firstNode?.value) // "folder1" const lastNode = tree.getLastNode() console.log(lastNode?.value) // "folder2" ``` #### Sequential Navigation Navigate to the next or previous node in the tree traversal order: ```ts const nextNode = tree.getNextNode('file1') console.log(nextNode?.value) // "file2" const previousNode = tree.getPreviousNode('file2') console.log(previousNode?.value) // "file1" ``` ### Hierarchical Relationships #### Parent and Children Get parent and descendant nodes: ```ts // Get parent node const parentNode = tree.getParentNode('file1') console.log(parentNode?.value) // "folder1" // Get all ancestor nodes const ancestors = tree.getParentNodes('file3') console.log(ancestors.map((n) => n.value)) // ["folder2", "subfolder1"] // Get all descendant nodes const descendants = tree.getDescendantNodes('folder1') console.log(descendants.map((n) => n.value)) // ["file1", "file2"] // Get descendant values only const descendantValues = tree.getDescendantValues('folder2') console.log(descendantValues) // ["subfolder1", "file3"] ``` #### Sibling Navigation Navigate between sibling nodes: ```ts // Assuming we have the index path of "file1" const indexPath = tree.getIndexPath('file1') // [0, 0] const nextSibling = tree.getNextSibling(indexPath) console.log(nextSibling?.value) // "file2" const previousSibling = tree.getPreviousSibling(indexPath) console.log(previousSibling) // undefined (no previous sibling) // Get all siblings const siblings = tree.getSiblingNodes(indexPath) console.log(siblings.map((n) => n.value)) // ["file1", "file2"] ``` ### Index Path Operations Work with index paths to identify node positions: ```ts // Get index path for a value const indexPath = tree.getIndexPath('file3') console.log(indexPath) // [1, 0, 0] // Get value from index path const value = tree.getValue([1, 0, 0]) console.log(value) // "file3" // Get full value path (all ancestors + node) const valuePath = tree.getValuePath([1, 0, 0]) console.log(valuePath) // ["folder2", "subfolder1", "file3"] // Get node at specific index path const node = tree.at([1, 0]) console.log(node?.value) // "subfolder1" ``` ### Tree Queries #### Branch and Leaf Detection ```ts // Check if a node is a branch (has children) const folder1Node = tree.findNode('folder1') const isBranch = tree.isBranchNode(folder1Node!) console.log(isBranch) // true // Get all branch values const branchValues = tree.getBranchValues() console.log(branchValues) // ["folder1", "folder2", "subfolder1"] ``` #### Tree Traversal Visit all nodes with custom logic: ```ts tree.visit({ onEnter: (node, indexPath) => { console.log(`Visiting: ${node.value} at depth ${indexPath.length}`) // Skip certain branches if (node.value === 'folder2') { return 'skip' // Skip this branch and its children } }, }) ``` #### Filtering Create a new tree with filtered nodes: ```ts // Keep only nodes that match criteria const filteredTree = tree.filter((node, indexPath) => { return node.value.includes('file') // Only keep files }) console.log(filteredTree.getValues()) // ["file1", "file2", "file3"] ``` ### Tree Manipulation #### Adding Nodes ```ts const newFile = { value: 'newfile', label: 'New File.txt' } // Insert after a specific node const indexPath = tree.getIndexPath('file1') const updatedTree = tree.insertAfter(indexPath!, [newFile]) // Insert before a specific node const updatedTree2 = tree.insertBefore(indexPath!, [newFile]) ``` #### Removing Nodes ```ts const indexPath = tree.getIndexPath('file2') const updatedTree = tree.remove([indexPath!]) console.log(updatedTree.getValues()) // file2 is removed ``` #### Moving Nodes ```ts const fromIndexPaths = [tree.getIndexPath('file1')!] const toIndexPath = tree.getIndexPath('folder2')! const updatedTree = tree.move(fromIndexPaths, toIndexPath) // file1 is now moved under folder2 ``` #### Replacing Nodes ```ts const indexPath = tree.getIndexPath('file1')! const newNode = { value: 'replacedfile', label: 'Replaced File.txt' } const updatedTree = tree.replace(indexPath, newNode) ``` ### Utility Methods #### Flattening Convert the tree to a flat structure: ```ts const flatNodes = tree.flatten() console.log(flatNodes.map((n) => ({ value: n.value, depth: n._indexPath.length }))) // [{ value: "folder1", depth: 1 }, { value: "file1", depth: 2 }, ...] ``` #### Getting All Values ```ts const allValues = tree.getValues() console.log(allValues) // ["folder1", "file1", "file2", "folder2", "subfolder1", "file3"] ``` #### Depth Calculation ```ts const depth = tree.getDepth('file3') console.log(depth) // 3 (root -> folder2 -> subfolder1 -> file3) ``` ### Working with Custom Node Types You can customize how the tree collection interprets your data: ```ts interface CustomNode { id: string name: string items?: CustomNode[] isDisabled?: boolean } const customTree = createTreeCollection({ rootNode: { id: 'root', name: 'Root', items: [ { id: '1', name: 'Item 1', isDisabled: false }, { id: '2', name: 'Item 2', isDisabled: true }, ], }, nodeToValue: (node) => node.id, nodeToString: (node) => node.name, nodeToChildren: (node) => node.items, isNodeDisabled: (node) => node.isDisabled ?? false, }) ``` ### Creating Trees from File Paths Create a tree structure from file paths: ```ts import { createFileTreeCollection } from '@ark-ui/react/collection' const paths = ['src/components/Button.tsx', 'src/components/Input.tsx', 'src/utils/helpers.ts', 'docs/README.md'] const fileTree = createFileTreeCollection(paths) console.log(fileTree.getBranchValues()) // ["src", "components", "utils", "docs"] ``` > **Good to know**: Tree collections are immutable - all modification methods return a new tree instance rather than > modifying the original. # Tree Collection (SVELTE) A tree collection is designed to manage hierarchical data structures like file systems, navigation menus, or organization charts. It provides powerful methods for traversing, manipulating, and querying tree structures. ```ts import { createTreeCollection } from '@ark-ui/react/collection' const treeData = { value: 'root', label: 'Root', children: [ { value: 'folder1', label: 'Folder 1', children: [ { value: 'file1', label: 'File 1.txt' }, { value: 'file2', label: 'File 2.txt' }, ], }, { value: 'folder2', label: 'Folder 2', children: [ { value: 'subfolder1', label: 'Subfolder 1', children: [{ value: 'file3', label: 'File 3.txt' }], }, ], }, ], } const tree = createTreeCollection({ rootNode: treeData }) ``` ### Navigation Methods The tree collection provides various methods to navigate through the hierarchical structure. #### Getting First and Last Nodes ```ts const firstNode = tree.getFirstNode() console.log(firstNode?.value) // "folder1" const lastNode = tree.getLastNode() console.log(lastNode?.value) // "folder2" ``` #### Sequential Navigation Navigate to the next or previous node in the tree traversal order: ```ts const nextNode = tree.getNextNode('file1') console.log(nextNode?.value) // "file2" const previousNode = tree.getPreviousNode('file2') console.log(previousNode?.value) // "file1" ``` ### Hierarchical Relationships #### Parent and Children Get parent and descendant nodes: ```ts // Get parent node const parentNode = tree.getParentNode('file1') console.log(parentNode?.value) // "folder1" // Get all ancestor nodes const ancestors = tree.getParentNodes('file3') console.log(ancestors.map((n) => n.value)) // ["folder2", "subfolder1"] // Get all descendant nodes const descendants = tree.getDescendantNodes('folder1') console.log(descendants.map((n) => n.value)) // ["file1", "file2"] // Get descendant values only const descendantValues = tree.getDescendantValues('folder2') console.log(descendantValues) // ["subfolder1", "file3"] ``` #### Sibling Navigation Navigate between sibling nodes: ```ts // Assuming we have the index path of "file1" const indexPath = tree.getIndexPath('file1') // [0, 0] const nextSibling = tree.getNextSibling(indexPath) console.log(nextSibling?.value) // "file2" const previousSibling = tree.getPreviousSibling(indexPath) console.log(previousSibling) // undefined (no previous sibling) // Get all siblings const siblings = tree.getSiblingNodes(indexPath) console.log(siblings.map((n) => n.value)) // ["file1", "file2"] ``` ### Index Path Operations Work with index paths to identify node positions: ```ts // Get index path for a value const indexPath = tree.getIndexPath('file3') console.log(indexPath) // [1, 0, 0] // Get value from index path const value = tree.getValue([1, 0, 0]) console.log(value) // "file3" // Get full value path (all ancestors + node) const valuePath = tree.getValuePath([1, 0, 0]) console.log(valuePath) // ["folder2", "subfolder1", "file3"] // Get node at specific index path const node = tree.at([1, 0]) console.log(node?.value) // "subfolder1" ``` ### Tree Queries #### Branch and Leaf Detection ```ts // Check if a node is a branch (has children) const folder1Node = tree.findNode('folder1') const isBranch = tree.isBranchNode(folder1Node!) console.log(isBranch) // true // Get all branch values const branchValues = tree.getBranchValues() console.log(branchValues) // ["folder1", "folder2", "subfolder1"] ``` #### Tree Traversal Visit all nodes with custom logic: ```ts tree.visit({ onEnter: (node, indexPath) => { console.log(`Visiting: ${node.value} at depth ${indexPath.length}`) // Skip certain branches if (node.value === 'folder2') { return 'skip' // Skip this branch and its children } }, }) ``` #### Filtering Create a new tree with filtered nodes: ```ts // Keep only nodes that match criteria const filteredTree = tree.filter((node, indexPath) => { return node.value.includes('file') // Only keep files }) console.log(filteredTree.getValues()) // ["file1", "file2", "file3"] ``` ### Tree Manipulation #### Adding Nodes ```ts const newFile = { value: 'newfile', label: 'New File.txt' } // Insert after a specific node const indexPath = tree.getIndexPath('file1') const updatedTree = tree.insertAfter(indexPath!, [newFile]) // Insert before a specific node const updatedTree2 = tree.insertBefore(indexPath!, [newFile]) ``` #### Removing Nodes ```ts const indexPath = tree.getIndexPath('file2') const updatedTree = tree.remove([indexPath!]) console.log(updatedTree.getValues()) // file2 is removed ``` #### Moving Nodes ```ts const fromIndexPaths = [tree.getIndexPath('file1')!] const toIndexPath = tree.getIndexPath('folder2')! const updatedTree = tree.move(fromIndexPaths, toIndexPath) // file1 is now moved under folder2 ``` #### Replacing Nodes ```ts const indexPath = tree.getIndexPath('file1')! const newNode = { value: 'replacedfile', label: 'Replaced File.txt' } const updatedTree = tree.replace(indexPath, newNode) ``` ### Utility Methods #### Flattening Convert the tree to a flat structure: ```ts const flatNodes = tree.flatten() console.log(flatNodes.map((n) => ({ value: n.value, depth: n._indexPath.length }))) // [{ value: "folder1", depth: 1 }, { value: "file1", depth: 2 }, ...] ``` #### Getting All Values ```ts const allValues = tree.getValues() console.log(allValues) // ["folder1", "file1", "file2", "folder2", "subfolder1", "file3"] ``` #### Depth Calculation ```ts const depth = tree.getDepth('file3') console.log(depth) // 3 (root -> folder2 -> subfolder1 -> file3) ``` ### Working with Custom Node Types You can customize how the tree collection interprets your data: ```ts interface CustomNode { id: string name: string items?: CustomNode[] isDisabled?: boolean } const customTree = createTreeCollection({ rootNode: { id: 'root', name: 'Root', items: [ { id: '1', name: 'Item 1', isDisabled: false }, { id: '2', name: 'Item 2', isDisabled: true }, ], }, nodeToValue: (node) => node.id, nodeToString: (node) => node.name, nodeToChildren: (node) => node.items, isNodeDisabled: (node) => node.isDisabled ?? false, }) ``` ### Creating Trees from File Paths Create a tree structure from file paths: ```ts import { createFileTreeCollection } from '@ark-ui/react/collection' const paths = ['src/components/Button.tsx', 'src/components/Input.tsx', 'src/utils/helpers.ts', 'docs/README.md'] const fileTree = createFileTreeCollection(paths) console.log(fileTree.getBranchValues()) // ["src", "components", "utils", "docs"] ``` > **Good to know**: Tree collections are immutable - all modification methods return a new tree instance rather than > modifying the original. # Tree Collection (SOLID) A tree collection is designed to manage hierarchical data structures like file systems, navigation menus, or organization charts. It provides powerful methods for traversing, manipulating, and querying tree structures. ```ts import { createTreeCollection } from '@ark-ui/react/collection' const treeData = { value: 'root', label: 'Root', children: [ { value: 'folder1', label: 'Folder 1', children: [ { value: 'file1', label: 'File 1.txt' }, { value: 'file2', label: 'File 2.txt' }, ], }, { value: 'folder2', label: 'Folder 2', children: [ { value: 'subfolder1', label: 'Subfolder 1', children: [{ value: 'file3', label: 'File 3.txt' }], }, ], }, ], } const tree = createTreeCollection({ rootNode: treeData }) ``` ### Navigation Methods The tree collection provides various methods to navigate through the hierarchical structure. #### Getting First and Last Nodes ```ts const firstNode = tree.getFirstNode() console.log(firstNode?.value) // "folder1" const lastNode = tree.getLastNode() console.log(lastNode?.value) // "folder2" ``` #### Sequential Navigation Navigate to the next or previous node in the tree traversal order: ```ts const nextNode = tree.getNextNode('file1') console.log(nextNode?.value) // "file2" const previousNode = tree.getPreviousNode('file2') console.log(previousNode?.value) // "file1" ``` ### Hierarchical Relationships #### Parent and Children Get parent and descendant nodes: ```ts // Get parent node const parentNode = tree.getParentNode('file1') console.log(parentNode?.value) // "folder1" // Get all ancestor nodes const ancestors = tree.getParentNodes('file3') console.log(ancestors.map((n) => n.value)) // ["folder2", "subfolder1"] // Get all descendant nodes const descendants = tree.getDescendantNodes('folder1') console.log(descendants.map((n) => n.value)) // ["file1", "file2"] // Get descendant values only const descendantValues = tree.getDescendantValues('folder2') console.log(descendantValues) // ["subfolder1", "file3"] ``` #### Sibling Navigation Navigate between sibling nodes: ```ts // Assuming we have the index path of "file1" const indexPath = tree.getIndexPath('file1') // [0, 0] const nextSibling = tree.getNextSibling(indexPath) console.log(nextSibling?.value) // "file2" const previousSibling = tree.getPreviousSibling(indexPath) console.log(previousSibling) // undefined (no previous sibling) // Get all siblings const siblings = tree.getSiblingNodes(indexPath) console.log(siblings.map((n) => n.value)) // ["file1", "file2"] ``` ### Index Path Operations Work with index paths to identify node positions: ```ts // Get index path for a value const indexPath = tree.getIndexPath('file3') console.log(indexPath) // [1, 0, 0] // Get value from index path const value = tree.getValue([1, 0, 0]) console.log(value) // "file3" // Get full value path (all ancestors + node) const valuePath = tree.getValuePath([1, 0, 0]) console.log(valuePath) // ["folder2", "subfolder1", "file3"] // Get node at specific index path const node = tree.at([1, 0]) console.log(node?.value) // "subfolder1" ``` ### Tree Queries #### Branch and Leaf Detection ```ts // Check if a node is a branch (has children) const folder1Node = tree.findNode('folder1') const isBranch = tree.isBranchNode(folder1Node!) console.log(isBranch) // true // Get all branch values const branchValues = tree.getBranchValues() console.log(branchValues) // ["folder1", "folder2", "subfolder1"] ``` #### Tree Traversal Visit all nodes with custom logic: ```ts tree.visit({ onEnter: (node, indexPath) => { console.log(`Visiting: ${node.value} at depth ${indexPath.length}`) // Skip certain branches if (node.value === 'folder2') { return 'skip' // Skip this branch and its children } }, }) ``` #### Filtering Create a new tree with filtered nodes: ```ts // Keep only nodes that match criteria const filteredTree = tree.filter((node, indexPath) => { return node.value.includes('file') // Only keep files }) console.log(filteredTree.getValues()) // ["file1", "file2", "file3"] ``` ### Tree Manipulation #### Adding Nodes ```ts const newFile = { value: 'newfile', label: 'New File.txt' } // Insert after a specific node const indexPath = tree.getIndexPath('file1') const updatedTree = tree.insertAfter(indexPath!, [newFile]) // Insert before a specific node const updatedTree2 = tree.insertBefore(indexPath!, [newFile]) ``` #### Removing Nodes ```ts const indexPath = tree.getIndexPath('file2') const updatedTree = tree.remove([indexPath!]) console.log(updatedTree.getValues()) // file2 is removed ``` #### Moving Nodes ```ts const fromIndexPaths = [tree.getIndexPath('file1')!] const toIndexPath = tree.getIndexPath('folder2')! const updatedTree = tree.move(fromIndexPaths, toIndexPath) // file1 is now moved under folder2 ``` #### Replacing Nodes ```ts const indexPath = tree.getIndexPath('file1')! const newNode = { value: 'replacedfile', label: 'Replaced File.txt' } const updatedTree = tree.replace(indexPath, newNode) ``` ### Utility Methods #### Flattening Convert the tree to a flat structure: ```ts const flatNodes = tree.flatten() console.log(flatNodes.map((n) => ({ value: n.value, depth: n._indexPath.length }))) // [{ value: "folder1", depth: 1 }, { value: "file1", depth: 2 }, ...] ``` #### Getting All Values ```ts const allValues = tree.getValues() console.log(allValues) // ["folder1", "file1", "file2", "folder2", "subfolder1", "file3"] ``` #### Depth Calculation ```ts const depth = tree.getDepth('file3') console.log(depth) // 3 (root -> folder2 -> subfolder1 -> file3) ``` ### Working with Custom Node Types You can customize how the tree collection interprets your data: ```ts interface CustomNode { id: string name: string items?: CustomNode[] isDisabled?: boolean } const customTree = createTreeCollection({ rootNode: { id: 'root', name: 'Root', items: [ { id: '1', name: 'Item 1', isDisabled: false }, { id: '2', name: 'Item 2', isDisabled: true }, ], }, nodeToValue: (node) => node.id, nodeToString: (node) => node.name, nodeToChildren: (node) => node.items, isNodeDisabled: (node) => node.isDisabled ?? false, }) ``` ### Creating Trees from File Paths Create a tree structure from file paths: ```ts import { createFileTreeCollection } from '@ark-ui/react/collection' const paths = ['src/components/Button.tsx', 'src/components/Input.tsx', 'src/utils/helpers.ts', 'docs/README.md'] const fileTree = createFileTreeCollection(paths) console.log(fileTree.getBranchValues()) // ["src", "components", "utils", "docs"] ``` > **Good to know**: Tree collections are immutable - all modification methods return a new tree instance rather than > modifying the original. # Async List (REACT) The `useAsyncList` hook manages asynchronous data operations for list collections. It provides a comprehensive solution for loading, filtering, sorting, and paginating data with built-in loading states, error handling, and request cancellation. ```tsx import { useAsyncList } from '@ark-ui/react/collection' const list = useAsyncList({ async load({ signal }) { const response = await fetch('/api/users', { signal }) const users = await response.json() return { items: users } }, }) console.log(list.items) // User[] console.log(list.loading) // boolean console.log(list.error) // Error | null ``` ## Examples ### Loading Data Load data asynchronously from an API using the `load` function and update the list when the data is ready. **Example: async-list/reload** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as quote}
                    "{quote.quote}"
                    — {quote.author}
                    {/each}
                    ``` ### Infinite Loading Implement pagination by returning a cursor that indicates more data is available. **Example: async-list/infinite-loading** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list.items.length} posts {list.cursor && ` (more available)`} {list.cursor && ( )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((post, index) => (
                    {index + 1}. {post.title}
                    {post.body}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list().items.length} posts {list().cursor && ` (more available)`} {list().cursor && ( )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(post, index) => (
                    {index() + 1}. {post.title}
                    {post.body}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Loaded {list().items.length} posts {#if list().cursor}(more available){/if} {#if list().cursor} {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as post, index}
                    {index + 1}. {post.title}
                    {post.body}
                    {/each}
                    ``` ### Filtering Filter data based on user input with automatic debouncing and loading states. **Example: async-list/filter** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Searching )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }: { filterText?: string }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Searching )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Searching {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No results found
                    {/if}
                    ``` ### Sorting (Client-side) Sort data on the client side after loading from the server. **Example: async-list/sort-client-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { useCollator } from '@ark-ui/react/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator.compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list.sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = list.sortDescriptor return (
                    {list.loading && (
                    Loading
                    )} {list.error &&
                    Error: {list.error.message}
                    }
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {[ { key: 'name', label: 'Name' }, { key: 'username', label: 'Username' }, { key: 'email', label: 'Email' }, ].map(({ key, label }) => ( ))} {list.items.map((user) => ( ))}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { useCollator } from '@ark-ui/solid/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator().compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list().sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = () => list().sortDescriptor return (
                    {list().loading && (
                    Loading
                    )} {list().error &&
                    Error: {list().error.message}
                    }
                    Sorted by: {descriptor() ? `${descriptor()?.column} (${descriptor()?.direction})` : 'none'}
                    {({ key, label }) => ( )} {(user) => ( )}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading}
                    Loading
                    {/if} {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {#each columns as { key, label }} {/each} {#each list().items as user} {/each}
                    handleSort(key as keyof User)}> {label} {#if list().sortDescriptor?.column === key} {#if list().sortDescriptor?.direction === 'ascending'} {:else} {/if} {:else} {/if}
                    {user.name} {user.username} {user.email}
                    ``` ### Sorting (Server-side) Send sort parameters to the server and reload data when sorting changes. **Example: async-list/sort-server-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list.sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list().sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as product}
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    {/each}
                    ``` ### Dependencies Automatically reload data when dependencies change, such as filter selections or external state. **Example: async-list/dependencies** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import { useState } from 'react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = useState('') const [selectedRole, setSelectedRole] = useState('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), dependencies: [selectedDepartment, selectedRole], async load({ filterText }) { await delay(400) let items = mockUsers if (selectedDepartment) { items = items.filter((user) => user.department === selectedDepartment) } if (selectedRole) { items = items.filter((user) => user.role === selectedRole) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    Found {list.items.length} users
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = createSignal('') const [selectedRole, setSelectedRole] = createSignal('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), get dependencies() { return [selectedDepartment(), selectedRole()] }, async load({ filterText }: { filterText?: string }) { await delay(400) let items = mockUsers if (selectedDepartment()) { items = items.filter((user) => user.department === selectedDepartment()) } if (selectedRole()) { items = items.filter((user) => user.role === selectedRole()) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    Found {list().items.length} users
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Found {list().items.length} users
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No users found with current filters
                    {/if}
                    ``` ## API Reference ### Props - **load** (`(params: LoadParams) => Promise>`) - Function to load data asynchronously - **sort** (`(params: SortParams) => Promise> | SortResult`) - Optional function for client-side sorting - **autoReload** (`boolean`, default: `false`) - Whether to automatically reload data on mount - **initialItems** (`T[]`, default: `[]`) - Initial items to display before first load - **dependencies** (`any[]`, default: `[]`) - Values that trigger a reload when changed - **initialFilterText** (`string`, default: `''`) - Initial filter text value - **initialSortDescriptor** (`SortDescriptor | null`) - Initial sort configuration ### Load Parameters The `load` function receives an object with the following properties: - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration - **signal** (`AbortSignal`) - AbortController signal for request cancellation ### Load Result The `load` function should return an object with: - **items** (`T[]`) - The loaded items - **cursor** (`C | undefined`) - Optional cursor for next page ### Sort Parameters The `sort` function receives an object with: - **items** (`T[]`) - Current items to sort - **descriptor** (`SortDescriptor`) - Sort configuration with `column` and `direction` ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **items** (`T[]`) - Current list of items - **loading** (`boolean`) - Whether a load operation is in progress - **error** (`Error | null`) - Any error from the last operation - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration #### Methods - **reload** (`() => void`) - Reload data from the beginning - **loadMore** (`() => void`) - Load more items (when cursor is available) - **setFilterText** (`(text: string) => void`) - Set filter text and reload - **sort** (`(descriptor: SortDescriptor) => void`) - Apply sorting #### Types ```tsx interface SortDescriptor { column: string direction: 'ascending' | 'descending' } interface LoadParams { cursor?: C filterText: string sortDescriptor?: SortDescriptor | null signal: AbortSignal } interface LoadResult { items: T[] cursor?: C } ``` # Async List (VUE) The `useAsyncList` hook manages asynchronous data operations for list collections. It provides a comprehensive solution for loading, filtering, sorting, and paginating data with built-in loading states, error handling, and request cancellation. ```tsx import { useAsyncList } from '@ark-ui/react/collection' const list = useAsyncList({ async load({ signal }) { const response = await fetch('/api/users', { signal }) const users = await response.json() return { items: users } }, }) console.log(list.items) // User[] console.log(list.loading) // boolean console.log(list.error) // Error | null ``` ## Examples ### Loading Data Load data asynchronously from an API using the `load` function and update the list when the data is ready. **Example: async-list/reload** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as quote}
                    "{quote.quote}"
                    — {quote.author}
                    {/each}
                    ``` ### Infinite Loading Implement pagination by returning a cursor that indicates more data is available. **Example: async-list/infinite-loading** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list.items.length} posts {list.cursor && ` (more available)`} {list.cursor && ( )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((post, index) => (
                    {index + 1}. {post.title}
                    {post.body}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list().items.length} posts {list().cursor && ` (more available)`} {list().cursor && ( )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(post, index) => (
                    {index() + 1}. {post.title}
                    {post.body}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Loaded {list().items.length} posts {#if list().cursor}(more available){/if} {#if list().cursor} {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as post, index}
                    {index + 1}. {post.title}
                    {post.body}
                    {/each}
                    ``` ### Filtering Filter data based on user input with automatic debouncing and loading states. **Example: async-list/filter** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Searching )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }: { filterText?: string }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Searching )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Searching {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No results found
                    {/if}
                    ``` ### Sorting (Client-side) Sort data on the client side after loading from the server. **Example: async-list/sort-client-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { useCollator } from '@ark-ui/react/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator.compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list.sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = list.sortDescriptor return (
                    {list.loading && (
                    Loading
                    )} {list.error &&
                    Error: {list.error.message}
                    }
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {[ { key: 'name', label: 'Name' }, { key: 'username', label: 'Username' }, { key: 'email', label: 'Email' }, ].map(({ key, label }) => ( ))} {list.items.map((user) => ( ))}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { useCollator } from '@ark-ui/solid/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator().compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list().sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = () => list().sortDescriptor return (
                    {list().loading && (
                    Loading
                    )} {list().error &&
                    Error: {list().error.message}
                    }
                    Sorted by: {descriptor() ? `${descriptor()?.column} (${descriptor()?.direction})` : 'none'}
                    {({ key, label }) => ( )} {(user) => ( )}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading}
                    Loading
                    {/if} {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {#each columns as { key, label }} {/each} {#each list().items as user} {/each}
                    handleSort(key as keyof User)}> {label} {#if list().sortDescriptor?.column === key} {#if list().sortDescriptor?.direction === 'ascending'} {:else} {/if} {:else} {/if}
                    {user.name} {user.username} {user.email}
                    ``` ### Sorting (Server-side) Send sort parameters to the server and reload data when sorting changes. **Example: async-list/sort-server-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list.sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list().sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as product}
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    {/each}
                    ``` ### Dependencies Automatically reload data when dependencies change, such as filter selections or external state. **Example: async-list/dependencies** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import { useState } from 'react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = useState('') const [selectedRole, setSelectedRole] = useState('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), dependencies: [selectedDepartment, selectedRole], async load({ filterText }) { await delay(400) let items = mockUsers if (selectedDepartment) { items = items.filter((user) => user.department === selectedDepartment) } if (selectedRole) { items = items.filter((user) => user.role === selectedRole) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    Found {list.items.length} users
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = createSignal('') const [selectedRole, setSelectedRole] = createSignal('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), get dependencies() { return [selectedDepartment(), selectedRole()] }, async load({ filterText }: { filterText?: string }) { await delay(400) let items = mockUsers if (selectedDepartment()) { items = items.filter((user) => user.department === selectedDepartment()) } if (selectedRole()) { items = items.filter((user) => user.role === selectedRole()) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    Found {list().items.length} users
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Found {list().items.length} users
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No users found with current filters
                    {/if}
                    ``` ## API Reference ### Props - **load** (`(params: LoadParams) => Promise>`) - Function to load data asynchronously - **sort** (`(params: SortParams) => Promise> | SortResult`) - Optional function for client-side sorting - **autoReload** (`boolean`, default: `false`) - Whether to automatically reload data on mount - **initialItems** (`T[]`, default: `[]`) - Initial items to display before first load - **dependencies** (`any[]`, default: `[]`) - Values that trigger a reload when changed - **initialFilterText** (`string`, default: `''`) - Initial filter text value - **initialSortDescriptor** (`SortDescriptor | null`) - Initial sort configuration ### Load Parameters The `load` function receives an object with the following properties: - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration - **signal** (`AbortSignal`) - AbortController signal for request cancellation ### Load Result The `load` function should return an object with: - **items** (`T[]`) - The loaded items - **cursor** (`C | undefined`) - Optional cursor for next page ### Sort Parameters The `sort` function receives an object with: - **items** (`T[]`) - Current items to sort - **descriptor** (`SortDescriptor`) - Sort configuration with `column` and `direction` ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **items** (`T[]`) - Current list of items - **loading** (`boolean`) - Whether a load operation is in progress - **error** (`Error | null`) - Any error from the last operation - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration #### Methods - **reload** (`() => void`) - Reload data from the beginning - **loadMore** (`() => void`) - Load more items (when cursor is available) - **setFilterText** (`(text: string) => void`) - Set filter text and reload - **sort** (`(descriptor: SortDescriptor) => void`) - Apply sorting #### Types ```tsx interface SortDescriptor { column: string direction: 'ascending' | 'descending' } interface LoadParams { cursor?: C filterText: string sortDescriptor?: SortDescriptor | null signal: AbortSignal } interface LoadResult { items: T[] cursor?: C } ``` # Async List (SVELTE) The `useAsyncList` hook manages asynchronous data operations for list collections. It provides a comprehensive solution for loading, filtering, sorting, and paginating data with built-in loading states, error handling, and request cancellation. ```tsx import { useAsyncList } from '@ark-ui/react/collection' const list = useAsyncList({ async load({ signal }) { const response = await fetch('/api/users', { signal }) const users = await response.json() return { items: users } }, }) console.log(list.items) // User[] console.log(list.loading) // boolean console.log(list.error) // Error | null ``` ## Examples ### Loading Data Load data asynchronously from an API using the `load` function and update the list when the data is ready. **Example: async-list/reload** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as quote}
                    "{quote.quote}"
                    — {quote.author}
                    {/each}
                    ``` ### Infinite Loading Implement pagination by returning a cursor that indicates more data is available. **Example: async-list/infinite-loading** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list.items.length} posts {list.cursor && ` (more available)`} {list.cursor && ( )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((post, index) => (
                    {index + 1}. {post.title}
                    {post.body}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list().items.length} posts {list().cursor && ` (more available)`} {list().cursor && ( )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(post, index) => (
                    {index() + 1}. {post.title}
                    {post.body}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Loaded {list().items.length} posts {#if list().cursor}(more available){/if} {#if list().cursor} {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as post, index}
                    {index + 1}. {post.title}
                    {post.body}
                    {/each}
                    ``` ### Filtering Filter data based on user input with automatic debouncing and loading states. **Example: async-list/filter** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Searching )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }: { filterText?: string }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Searching )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Searching {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No results found
                    {/if}
                    ``` ### Sorting (Client-side) Sort data on the client side after loading from the server. **Example: async-list/sort-client-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { useCollator } from '@ark-ui/react/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator.compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list.sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = list.sortDescriptor return (
                    {list.loading && (
                    Loading
                    )} {list.error &&
                    Error: {list.error.message}
                    }
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {[ { key: 'name', label: 'Name' }, { key: 'username', label: 'Username' }, { key: 'email', label: 'Email' }, ].map(({ key, label }) => ( ))} {list.items.map((user) => ( ))}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { useCollator } from '@ark-ui/solid/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator().compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list().sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = () => list().sortDescriptor return (
                    {list().loading && (
                    Loading
                    )} {list().error &&
                    Error: {list().error.message}
                    }
                    Sorted by: {descriptor() ? `${descriptor()?.column} (${descriptor()?.direction})` : 'none'}
                    {({ key, label }) => ( )} {(user) => ( )}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading}
                    Loading
                    {/if} {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {#each columns as { key, label }} {/each} {#each list().items as user} {/each}
                    handleSort(key as keyof User)}> {label} {#if list().sortDescriptor?.column === key} {#if list().sortDescriptor?.direction === 'ascending'} {:else} {/if} {:else} {/if}
                    {user.name} {user.username} {user.email}
                    ``` ### Sorting (Server-side) Send sort parameters to the server and reload data when sorting changes. **Example: async-list/sort-server-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list.sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list().sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as product}
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    {/each}
                    ``` ### Dependencies Automatically reload data when dependencies change, such as filter selections or external state. **Example: async-list/dependencies** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import { useState } from 'react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = useState('') const [selectedRole, setSelectedRole] = useState('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), dependencies: [selectedDepartment, selectedRole], async load({ filterText }) { await delay(400) let items = mockUsers if (selectedDepartment) { items = items.filter((user) => user.department === selectedDepartment) } if (selectedRole) { items = items.filter((user) => user.role === selectedRole) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    Found {list.items.length} users
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = createSignal('') const [selectedRole, setSelectedRole] = createSignal('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), get dependencies() { return [selectedDepartment(), selectedRole()] }, async load({ filterText }: { filterText?: string }) { await delay(400) let items = mockUsers if (selectedDepartment()) { items = items.filter((user) => user.department === selectedDepartment()) } if (selectedRole()) { items = items.filter((user) => user.role === selectedRole()) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    Found {list().items.length} users
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Found {list().items.length} users
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No users found with current filters
                    {/if}
                    ``` ## API Reference ### Props - **load** (`(params: LoadParams) => Promise>`) - Function to load data asynchronously - **sort** (`(params: SortParams) => Promise> | SortResult`) - Optional function for client-side sorting - **autoReload** (`boolean`, default: `false`) - Whether to automatically reload data on mount - **initialItems** (`T[]`, default: `[]`) - Initial items to display before first load - **dependencies** (`any[]`, default: `[]`) - Values that trigger a reload when changed - **initialFilterText** (`string`, default: `''`) - Initial filter text value - **initialSortDescriptor** (`SortDescriptor | null`) - Initial sort configuration ### Load Parameters The `load` function receives an object with the following properties: - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration - **signal** (`AbortSignal`) - AbortController signal for request cancellation ### Load Result The `load` function should return an object with: - **items** (`T[]`) - The loaded items - **cursor** (`C | undefined`) - Optional cursor for next page ### Sort Parameters The `sort` function receives an object with: - **items** (`T[]`) - Current items to sort - **descriptor** (`SortDescriptor`) - Sort configuration with `column` and `direction` ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **items** (`T[]`) - Current list of items - **loading** (`boolean`) - Whether a load operation is in progress - **error** (`Error | null`) - Any error from the last operation - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration #### Methods - **reload** (`() => void`) - Reload data from the beginning - **loadMore** (`() => void`) - Load more items (when cursor is available) - **setFilterText** (`(text: string) => void`) - Set filter text and reload - **sort** (`(descriptor: SortDescriptor) => void`) - Apply sorting #### Types ```tsx interface SortDescriptor { column: string direction: 'ascending' | 'descending' } interface LoadParams { cursor?: C filterText: string sortDescriptor?: SortDescriptor | null signal: AbortSignal } interface LoadResult { items: T[] cursor?: C } ``` # Async List (SOLID) The `useAsyncList` hook manages asynchronous data operations for list collections. It provides a comprehensive solution for loading, filtering, sorting, and paginating data with built-in loading states, error handling, and request cancellation. ```tsx import { useAsyncList } from '@ark-ui/react/collection' const list = useAsyncList({ async load({ signal }) { const response = await fetch('/api/users', { signal }) const users = await response.json() return { items: users } }, }) console.log(list.items) // User[] console.log(list.loading) // boolean console.log(list.error) // Error | null ``` ## Examples ### Loading Data Load data asynchronously from an API using the `load` function and update the list when the data is ready. **Example: async-list/reload** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Quote { id: number quote: string author: string } export const Reload = () => { const list = useAsyncList({ autoReload: true, async load() { const response = await fetch(`https://dummyjson.com/quotes?limit=4&skip=${Math.floor(Math.random() * 50)}`) if (!response.ok) { throw new Error('Failed to fetch quotes') } const data = await response.json() return { items: data.quotes } }, }) return (
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(quote) => (
                    "{quote.quote}"
                    — {quote.author}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as quote}
                    "{quote.quote}"
                    — {quote.author}
                    {/each}
                    ``` ### Infinite Loading Implement pagination by returning a cursor that indicates more data is available. **Example: async-list/infinite-loading** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list.items.length} posts {list.cursor && ` (more available)`} {list.cursor && ( )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((post, index) => (
                    {index + 1}. {post.title}
                    {post.body}
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface Post { userId: number id: number title: string body: string } export const InfiniteLoading = () => { const list = useAsyncList({ autoReload: true, async load({ cursor }) { const page = cursor || 1 const start = (page - 1) * LIMIT const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_start=${start}&_limit=${LIMIT}`) if (!response.ok) { throw new Error('Failed to fetch posts') } const posts: Post[] = await response.json() const hasNextPage = posts.length === LIMIT return { items: posts, cursor: hasNextPage ? page + 1 : undefined, } }, }) return (
                    Loaded {list().items.length} posts {list().cursor && ` (more available)`} {list().cursor && ( )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(post, index) => (
                    {index() + 1}. {post.title}
                    {post.body}
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Loaded {list().items.length} posts {#if list().cursor}(more available){/if} {#if list().cursor} {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as post, index}
                    {index + 1}. {post.title}
                    {post.body}
                    {/each}
                    ``` ### Filtering Filter data based on user input with automatic debouncing and loading states. **Example: async-list/filter** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Searching )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 4 interface User { id: number name: string email: string department: string role: string } export const Filter = () => { const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), async load({ filterText }: { filterText?: string }) { await delay(500) if (!filterText) { return { items: mockUsers.slice(0, LIMIT) } } const filtered = mockUsers.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) return { items: filtered.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Searching )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading &&
                    No results found
                    }
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Searching {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No results found
                    {/if}
                    ``` ### Sorting (Client-side) Sort data on the client side after loading from the server. **Example: async-list/sort-client-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { useCollator } from '@ark-ui/react/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator.compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list.sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = list.sortDescriptor return (
                    {list.loading && (
                    Loading
                    )} {list.error &&
                    Error: {list.error.message}
                    }
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {[ { key: 'name', label: 'Name' }, { key: 'username', label: 'Username' }, { key: 'email', label: 'Email' }, ].map(({ key, label }) => ( ))} {list.items.map((user) => ( ))}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { useCollator } from '@ark-ui/solid/locale' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/async-list.module.css' interface User { id: number name: string username: string email: string phone: string website: string } export const SortClientSide = () => { const collator = useCollator() const list = useAsyncList({ autoReload: true, load: async () => { const response = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5') const data = await response.json() return { items: data } }, sort({ items, descriptor }) { return { items: items.sort((a, b) => { const { column, direction } = descriptor let cmp = collator().compare(String(a[column]), String(b[column])) if (direction === 'descending') { cmp *= -1 } return cmp }), } }, }) const handleSort = (column: keyof User) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof User) => { const current = list().sortDescriptor if (current?.column !== column) return return current.direction === 'ascending' ? : } const descriptor = () => list().sortDescriptor return (
                    {list().loading && (
                    Loading
                    )} {list().error &&
                    Error: {list().error.message}
                    }
                    Sorted by: {descriptor() ? `${descriptor()?.column} (${descriptor()?.direction})` : 'none'}
                    {({ key, label }) => ( )} {(user) => ( )}
                    handleSort(key as keyof User)}> {label} {getSortIcon(key as keyof User)}
                    {user.name} {user.username} {user.email}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading}
                    Loading
                    {/if} {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Sorted by: {descriptor ? `${descriptor.column} (${descriptor.direction})` : 'none'}
                    {#each columns as { key, label }} {/each} {#each list().items as user} {/each}
                    handleSort(key as keyof User)}> {label} {#if list().sortDescriptor?.column === key} {#if list().sortDescriptor?.direction === 'ascending'} {:else} {/if} {:else} {/if}
                    {user.name} {user.username} {user.email}
                    ``` ### Sorting (Server-side) Send sort parameters to the server and reload data when sorting changes. **Example: async-list/sort-server-side** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list.sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list.sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list.sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    {list.items.map((product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    ))}
                    ) } ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon, LoaderIcon } from 'lucide-solid' import { For } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/async-list.module.css' interface Product { id: number title: string price: number description: string category: string image: string rating: { rate: number count: number } } export const SortServerSide = () => { const list = useAsyncList({ autoReload: true, async load({ sortDescriptor }) { const url = new URL('https://fakestoreapi.com/products') url.searchParams.set('limit', '5') if (sortDescriptor) { const { direction } = sortDescriptor url.searchParams.set('sort', direction === 'ascending' ? 'asc' : 'desc') } const response = await fetch(url) const items = await response.json() return { items } }, }) const handleSort = (column: keyof Product) => { const currentSort = list().sortDescriptor let direction: 'ascending' | 'descending' = 'ascending' if (currentSort?.column === column && currentSort.direction === 'ascending') { direction = 'descending' } list().sort({ column, direction }) } const getSortIcon = (column: keyof Product) => { const desc = list().sortDescriptor if (desc?.column !== column) return return desc.direction === 'ascending' ? : } return (
                    {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    {(product) => (
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    {#each list().items as product}
                    {product.title}
                    {product.title}
                    ${product.price}
                    {product.category} • {product.rating.rate} ({product.rating.count} reviews)
                    {/each}
                    ``` ### Dependencies Automatically reload data when dependencies change, such as filter selections or external state. **Example: async-list/dependencies** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { LoaderIcon } from 'lucide-react' import { useState } from 'react' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = useState('') const [selectedRole, setSelectedRole] = useState('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), dependencies: [selectedDepartment, selectedRole], async load({ filterText }) { await delay(400) let items = mockUsers if (selectedDepartment) { items = items.filter((user) => user.department === selectedDepartment) } if (selectedRole) { items = items.filter((user) => user.role === selectedRole) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list.setFilterText(e.target.value)} /> {list.loading && ( Loading )}
                    {list.error &&
                    Error: {list.error.message}
                    }
                    Found {list.items.length} users
                    {list.items.map((user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    ))}
                    {list.items.length === 0 && !list.loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Solid ```tsx import { useAsyncList } from '@ark-ui/solid/collection' import { LoaderIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import field from 'styles/field.module.css' import styles from 'styles/async-list.module.css' const LIMIT = 5 interface User { id: number name: string email: string department: string role: string } export const Dependencies = () => { const [selectedDepartment, setSelectedDepartment] = createSignal('') const [selectedRole, setSelectedRole] = createSignal('') const list = useAsyncList({ initialItems: mockUsers.slice(0, LIMIT), get dependencies() { return [selectedDepartment(), selectedRole()] }, async load({ filterText }: { filterText?: string }) { await delay(400) let items = mockUsers if (selectedDepartment()) { items = items.filter((user) => user.department === selectedDepartment()) } if (selectedRole()) { items = items.filter((user) => user.role === selectedRole()) } if (filterText) { items = items.filter( (user) => user.name.toLowerCase().includes(filterText.toLowerCase()) || user.email.toLowerCase().includes(filterText.toLowerCase()), ) } return { items: items.slice(0, LIMIT) } }, }) return (
                    list().setFilterText(e.target.value)} /> {list().loading && ( Loading )}
                    {list().error &&
                    Error: {list().error.message}
                    }
                    Found {list().items.length} users
                    {(user) => (
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    )}
                    {list().items.length === 0 && !list().loading && (
                    No users found with current filters
                    )}
                    ) } const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) const departments = ['Engineering', 'Marketing', 'Sales', 'Support'] const roles = [ 'Senior Developer', 'Marketing Manager', 'Frontend Developer', 'Sales Representative', 'DevOps Engineer', 'Customer Success', 'Content Creator', 'Backend Developer', 'Account Manager', 'Technical Support', 'Brand Manager', 'Full Stack Developer', 'Sales Director', 'Support Manager', 'UI Designer', 'Digital Marketer', 'Mobile Developer', 'Business Development', 'Documentation Specialist', 'Social Media Manager', ] const mockUsers: User[] = [ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', department: 'Engineering', role: 'Senior Developer' }, { id: 2, name: 'Bob Smith', email: 'bob@example.com', department: 'Marketing', role: 'Marketing Manager' }, { id: 3, name: 'Carol Davis', email: 'carol@example.com', department: 'Engineering', role: 'Frontend Developer' }, { id: 4, name: 'David Wilson', email: 'david@example.com', department: 'Sales', role: 'Sales Representative' }, { id: 5, name: 'Eva Brown', email: 'eva@example.com', department: 'Engineering', role: 'DevOps Engineer' }, { id: 6, name: 'Frank Miller', email: 'frank@example.com', department: 'Support', role: 'Customer Success' }, { id: 7, name: 'Grace Lee', email: 'grace@example.com', department: 'Marketing', role: 'Content Creator' }, { id: 8, name: 'Henry Taylor', email: 'henry@example.com', department: 'Engineering', role: 'Backend Developer' }, { id: 9, name: 'Ivy Anderson', email: 'ivy@example.com', department: 'Sales', role: 'Account Manager' }, { id: 10, name: 'Jack Thompson', email: 'jack@example.com', department: 'Support', role: 'Technical Support' }, { id: 11, name: 'Kate Martinez', email: 'kate@example.com', department: 'Marketing', role: 'Brand Manager' }, { id: 12, name: 'Liam Garcia', email: 'liam@example.com', department: 'Engineering', role: 'Full Stack Developer' }, { id: 13, name: 'Mia Rodriguez', email: 'mia@example.com', department: 'Sales', role: 'Sales Director' }, { id: 14, name: 'Noah Lopez', email: 'noah@example.com', department: 'Support', role: 'Support Manager' }, { id: 15, name: 'Olivia White', email: 'olivia@example.com', department: 'Engineering', role: 'UI Designer' }, { id: 16, name: 'Paul Harris', email: 'paul@example.com', department: 'Marketing', role: 'Digital Marketer' }, { id: 17, name: 'Quinn Clark', email: 'quinn@example.com', department: 'Engineering', role: 'Mobile Developer' }, { id: 18, name: 'Ruby Lewis', email: 'ruby@example.com', department: 'Sales', role: 'Business Development' }, { id: 19, name: 'Sam Young', email: 'sam@example.com', department: 'Support', role: 'Documentation Specialist' }, { id: 20, name: 'Tina Walker', email: 'tina@example.com', department: 'Marketing', role: 'Social Media Manager' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    list().setFilterText(e.currentTarget.value)} /> {#if list().loading} Loading {/if}
                    {#if list().error}
                    Error: {list().error.message}
                    {/if}
                    Found {list().items.length} users
                    {#each list().items as user}
                    {user.name}
                    {user.email}
                    {user.department} • {user.role}
                    {/each}
                    {#if list().items.length === 0 && !list().loading}
                    No users found with current filters
                    {/if}
                    ``` ## API Reference ### Props - **load** (`(params: LoadParams) => Promise>`) - Function to load data asynchronously - **sort** (`(params: SortParams) => Promise> | SortResult`) - Optional function for client-side sorting - **autoReload** (`boolean`, default: `false`) - Whether to automatically reload data on mount - **initialItems** (`T[]`, default: `[]`) - Initial items to display before first load - **dependencies** (`any[]`, default: `[]`) - Values that trigger a reload when changed - **initialFilterText** (`string`, default: `''`) - Initial filter text value - **initialSortDescriptor** (`SortDescriptor | null`) - Initial sort configuration ### Load Parameters The `load` function receives an object with the following properties: - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration - **signal** (`AbortSignal`) - AbortController signal for request cancellation ### Load Result The `load` function should return an object with: - **items** (`T[]`) - The loaded items - **cursor** (`C | undefined`) - Optional cursor for next page ### Sort Parameters The `sort` function receives an object with: - **items** (`T[]`) - Current items to sort - **descriptor** (`SortDescriptor`) - Sort configuration with `column` and `direction` ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **items** (`T[]`) - Current list of items - **loading** (`boolean`) - Whether a load operation is in progress - **error** (`Error | null`) - Any error from the last operation - **cursor** (`C | undefined`) - Current cursor for pagination - **filterText** (`string`) - Current filter text - **sortDescriptor** (`SortDescriptor | null`) - Current sort configuration #### Methods - **reload** (`() => void`) - Reload data from the beginning - **loadMore** (`() => void`) - Load more items (when cursor is available) - **setFilterText** (`(text: string) => void`) - Set filter text and reload - **sort** (`(descriptor: SortDescriptor) => void`) - Apply sorting #### Types ```tsx interface SortDescriptor { column: string direction: 'ascending' | 'descending' } interface LoadParams { cursor?: C filterText: string sortDescriptor?: SortDescriptor | null signal: AbortSignal } interface LoadResult { items: T[] cursor?: C } ``` # List Selection (REACT) The `useListSelection` hook manages selection state in lists and collections. It supports single and multiple selection modes with operations like select, deselect, toggle, and clear. ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }, ], }) const selection = useListSelection({ collection, selectionMode: 'single', deselectable: true, }) console.log(selection.selectedValues) // ['apple', 'banana', 'cherry'] ``` ## Examples ### Basic By default, the hook supports single selection mode that can be deselected. > Set `deselectable` to `false` to prevent deselecting the current selection. **Example: list-selection/basic** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}
                    ``` ### Multiple Selection Set `selectionMode` to `multiple` to allow multiple items to be selected. **Example: list-selection/multiple** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues.length} of {collection.items.length} selected
                    {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {#each collection.items as item (item.value)} {/each}
                    ``` ### Range Selection Here's an example of how to implement range selection that extends the selection from the first selected item to the clicked item. **Example: list-selection/range** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: React.MouseEvent) => { if (event.shiftKey && selection.firstSelectedValue) { selection.extend(selection.firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: MouseEvent) => { const firstSelectedValue = selection.firstSelectedValue() if (event.shiftKey && firstSelectedValue) { selection.extend(firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ``` ## API Reference ### Props - **collection** (`ListCollection`) - The collection to manage selection for - **selectionMode** (`'single' | 'multiple' | 'none'`, default: `'single'`) - The selection mode - **deselectable** (`boolean`, default: `true`) - Whether selected items can be deselected - **initialSelectedValues** (`string[]`, default: `[]`) - Initial selected values - **resetOnCollectionChange** (`boolean`, default: `false`) - Whether to reset selection when collection changes ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **selectedValues** (`string[]`) - Array of currently selected values - **isEmpty** (`boolean`) - Whether no items are selected - **firstSelectedValue** (`string | null`) - The first selected value in collection order - **lastSelectedValue** (`string | null`) - The last selected value in collection order #### Query Methods - **isSelected** (`(value: string | null) => boolean`) - Check if a value is selected - **canSelect** (`(value: string) => boolean`) - Check if a value can be selected - **isAllSelected** (`() => boolean`) - Check if all items are selected - **isSomeSelected** (`() => boolean`) - Check if some items are selected #### Selection Methods - **select** (`(value: string, forceToggle?: boolean) => void`) - Select a value - **deselect** (`(value: string) => void`) - Deselect a value - **toggle** (`(value: string) => void`) - Toggle selection of a value - **replace** (`(value: string | null) => void`) - Replace selection with a single value - **extend** (`(anchorValue: string, targetValue: string) => void`) - Extend selection from anchor to target - **setSelectedValues** (`(values: string[]) => void`) - Set the selected values - **setSelection** (`(values: string[]) => void`) - Set the selection (alias for setSelectedValues) - **clear** (`() => void`) - Clear all selections - **resetSelection** (`() => void`) - Reset selection to initial state # List Selection (VUE) The `useListSelection` hook manages selection state in lists and collections. It supports single and multiple selection modes with operations like select, deselect, toggle, and clear. ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }, ], }) const selection = useListSelection({ collection, selectionMode: 'single', deselectable: true, }) console.log(selection.selectedValues) // ['apple', 'banana', 'cherry'] ``` ## Examples ### Basic By default, the hook supports single selection mode that can be deselected. > Set `deselectable` to `false` to prevent deselecting the current selection. **Example: list-selection/basic** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}
                    ``` ### Multiple Selection Set `selectionMode` to `multiple` to allow multiple items to be selected. **Example: list-selection/multiple** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues.length} of {collection.items.length} selected
                    {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {#each collection.items as item (item.value)} {/each}
                    ``` ### Range Selection Here's an example of how to implement range selection that extends the selection from the first selected item to the clicked item. **Example: list-selection/range** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: React.MouseEvent) => { if (event.shiftKey && selection.firstSelectedValue) { selection.extend(selection.firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: MouseEvent) => { const firstSelectedValue = selection.firstSelectedValue() if (event.shiftKey && firstSelectedValue) { selection.extend(firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ``` ## API Reference ### Props - **collection** (`ListCollection`) - The collection to manage selection for - **selectionMode** (`'single' | 'multiple' | 'none'`, default: `'single'`) - The selection mode - **deselectable** (`boolean`, default: `true`) - Whether selected items can be deselected - **initialSelectedValues** (`string[]`, default: `[]`) - Initial selected values - **resetOnCollectionChange** (`boolean`, default: `false`) - Whether to reset selection when collection changes ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **selectedValues** (`string[]`) - Array of currently selected values - **isEmpty** (`boolean`) - Whether no items are selected - **firstSelectedValue** (`string | null`) - The first selected value in collection order - **lastSelectedValue** (`string | null`) - The last selected value in collection order #### Query Methods - **isSelected** (`(value: string | null) => boolean`) - Check if a value is selected - **canSelect** (`(value: string) => boolean`) - Check if a value can be selected - **isAllSelected** (`() => boolean`) - Check if all items are selected - **isSomeSelected** (`() => boolean`) - Check if some items are selected #### Selection Methods - **select** (`(value: string, forceToggle?: boolean) => void`) - Select a value - **deselect** (`(value: string) => void`) - Deselect a value - **toggle** (`(value: string) => void`) - Toggle selection of a value - **replace** (`(value: string | null) => void`) - Replace selection with a single value - **extend** (`(anchorValue: string, targetValue: string) => void`) - Extend selection from anchor to target - **setSelectedValues** (`(values: string[]) => void`) - Set the selected values - **setSelection** (`(values: string[]) => void`) - Set the selection (alias for setSelectedValues) - **clear** (`() => void`) - Clear all selections - **resetSelection** (`() => void`) - Reset selection to initial state # List Selection (SVELTE) The `useListSelection` hook manages selection state in lists and collections. It supports single and multiple selection modes with operations like select, deselect, toggle, and clear. ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }, ], }) const selection = useListSelection({ collection, selectionMode: 'single', deselectable: true, }) console.log(selection.selectedValues) // ['apple', 'banana', 'cherry'] ``` ## Examples ### Basic By default, the hook supports single selection mode that can be deselected. > Set `deselectable` to `false` to prevent deselecting the current selection. **Example: list-selection/basic** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}
                    ``` ### Multiple Selection Set `selectionMode` to `multiple` to allow multiple items to be selected. **Example: list-selection/multiple** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues.length} of {collection.items.length} selected
                    {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {#each collection.items as item (item.value)} {/each}
                    ``` ### Range Selection Here's an example of how to implement range selection that extends the selection from the first selected item to the clicked item. **Example: list-selection/range** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: React.MouseEvent) => { if (event.shiftKey && selection.firstSelectedValue) { selection.extend(selection.firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: MouseEvent) => { const firstSelectedValue = selection.firstSelectedValue() if (event.shiftKey && firstSelectedValue) { selection.extend(firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ``` ## API Reference ### Props - **collection** (`ListCollection`) - The collection to manage selection for - **selectionMode** (`'single' | 'multiple' | 'none'`, default: `'single'`) - The selection mode - **deselectable** (`boolean`, default: `true`) - Whether selected items can be deselected - **initialSelectedValues** (`string[]`, default: `[]`) - Initial selected values - **resetOnCollectionChange** (`boolean`, default: `false`) - Whether to reset selection when collection changes ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **selectedValues** (`string[]`) - Array of currently selected values - **isEmpty** (`boolean`) - Whether no items are selected - **firstSelectedValue** (`string | null`) - The first selected value in collection order - **lastSelectedValue** (`string | null`) - The last selected value in collection order #### Query Methods - **isSelected** (`(value: string | null) => boolean`) - Check if a value is selected - **canSelect** (`(value: string) => boolean`) - Check if a value can be selected - **isAllSelected** (`() => boolean`) - Check if all items are selected - **isSomeSelected** (`() => boolean`) - Check if some items are selected #### Selection Methods - **select** (`(value: string, forceToggle?: boolean) => void`) - Select a value - **deselect** (`(value: string) => void`) - Deselect a value - **toggle** (`(value: string) => void`) - Toggle selection of a value - **replace** (`(value: string | null) => void`) - Replace selection with a single value - **extend** (`(anchorValue: string, targetValue: string) => void`) - Extend selection from anchor to target - **setSelectedValues** (`(values: string[]) => void`) - Set the selected values - **setSelection** (`(values: string[]) => void`) - Set the selection (alias for setSelectedValues) - **clear** (`() => void`) - Clear all selections - **resetSelection** (`() => void`) - Reset selection to initial state # List Selection (SOLID) The `useListSelection` hook manages selection state in lists and collections. It supports single and multiple selection modes with operations like select, deselect, toggle, and clear. ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' const collection = createListCollection({ items: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }, ], }) const selection = useListSelection({ collection, selectionMode: 'single', deselectable: true, }) console.log(selection.selectedValues) // ['apple', 'banana', 'cherry'] ``` ## Examples ### Basic By default, the hook supports single selection mode that can be deselected. > Set `deselectable` to `false` to prevent deselecting the current selection. **Example: list-selection/basic** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Basic = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, ], }) const selection = useListSelection({ collection }) return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}
                    ``` ### Multiple Selection Set `selectionMode` to `multiple` to allow multiple items to be selected. **Example: list-selection/multiple** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues.length} of {collection.items.length} selected
                    {collection.items.map((item) => ( ))}
                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Multiple = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleSelectAll = () => { if (selection.isAllSelected()) { selection.clear() } else { selection.setSelectedValues(collection.getValues()) } } return (
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {(item) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {selection.selectedValues().length} of {collection.items.length} selected
                    {#each collection.items as item (item.value)} {/each}
                    ``` ### Range Selection Here's an example of how to implement range selection that extends the selection from the first selected item to the clicked item. **Example: list-selection/range** #### React ```tsx import { createListCollection, useListSelection } from '@ark-ui/react/collection' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: React.MouseEvent) => { if (event.shiftKey && selection.firstSelectedValue) { selection.extend(selection.firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues.join(', ') || 'None'} {collection.items.map((item) => ( ))}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Solid ```tsx import { createListCollection, useListSelection } from '@ark-ui/solid/collection' import { For } from 'solid-js' import styles from 'styles/list-selection.module.css' export const Range = () => { const collection = createListCollection({ items: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, { label: 'Angular', value: 'angular' }, { label: 'Svelte', value: 'svelte' }, { label: 'Solid', value: 'solid' }, ], }) const selection = useListSelection({ collection, selectionMode: 'multiple', }) const handleItemClick = (value: string, event: MouseEvent) => { const firstSelectedValue = selection.firstSelectedValue() if (event.shiftKey && firstSelectedValue) { selection.extend(firstSelectedValue, value) } else if (event.ctrlKey || event.metaKey) { selection.toggle(value) } else { selection.replace(value) } } return (
                    Selected: {selection.selectedValues().join(', ') || 'None'} {(item) => ( )}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected: {selection.selectedValues().join(', ') || 'None'} {#each collection.items as item (item.value)} {/each}

                    Click to select • Shift+Click for range • Cmd/Ctrl+Click to toggle

                    ``` ## API Reference ### Props - **collection** (`ListCollection`) - The collection to manage selection for - **selectionMode** (`'single' | 'multiple' | 'none'`, default: `'single'`) - The selection mode - **deselectable** (`boolean`, default: `true`) - Whether selected items can be deselected - **initialSelectedValues** (`string[]`, default: `[]`) - Initial selected values - **resetOnCollectionChange** (`boolean`, default: `false`) - Whether to reset selection when collection changes ### Return Value The hook returns an object with the following properties and methods: #### State Properties - **selectedValues** (`string[]`) - Array of currently selected values - **isEmpty** (`boolean`) - Whether no items are selected - **firstSelectedValue** (`string | null`) - The first selected value in collection order - **lastSelectedValue** (`string | null`) - The last selected value in collection order #### Query Methods - **isSelected** (`(value: string | null) => boolean`) - Check if a value is selected - **canSelect** (`(value: string) => boolean`) - Check if a value can be selected - **isAllSelected** (`() => boolean`) - Check if all items are selected - **isSomeSelected** (`() => boolean`) - Check if some items are selected #### Selection Methods - **select** (`(value: string, forceToggle?: boolean) => void`) - Select a value - **deselect** (`(value: string) => void`) - Deselect a value - **toggle** (`(value: string) => void`) - Toggle selection of a value - **replace** (`(value: string | null) => void`) - Replace selection with a single value - **extend** (`(anchorValue: string, targetValue: string) => void`) - Extend selection from anchor to target - **setSelectedValues** (`(values: string[]) => void`) - Set the selected values - **setSelection** (`(values: string[]) => void`) - Set the selection (alias for setSelectedValues) - **clear** (`() => void`) - Clear all selections - **resetSelection** (`() => void`) - Reset selection to initial state # COMPONENTS --- # Accordion (REACT) ## Anatomy ```tsx ``` ## Examples ### Default Value Set the `defaultValue` prop to specify which item should be expanded by default. **Example: basic** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Controlled Use the `value` and `onValueChange` props to control the expanded items. **Example: controlled** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = useState([]) return ( setValue(details.value)}> {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = createSignal([]) return ( setValue(details.value)}> {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Root Provider An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Accordion, useAccordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion.value)} {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion, useAccordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion().value)} {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Value: {JSON.stringify(accordion().value)} {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Collapsible Use the `collapsible` prop to allow the user to collapse all panels. **Example: collapsible** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Multiple Use the `multiple` prop to allow multiple panels to be expanded simultaneously. **Example: multiple** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Horizontal By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout. **Example: horizontal** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Lazy Mount Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with `unmountOnExit` to unmount content when collapsed, freeing up resources. **Example: lazy-mount** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const LazyMount = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Context Use `Accordion.Context` or `useAccordionContext` to access the accordion state. **Example: context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context.value)}
                    context.focusedValue: {context.focusedValue || 'null'}
                    )}
                    {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    )}
                    {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(context)}
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    {/snippet}
                    {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Item State Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item. **Example: item-context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {items.map((item) => ( {item.title} {(context) => ( {context.expanded && Expanded} {context.focused && Focused} )}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {(item) => ( {item().title} {(context) => (
                    Expanded: {String(context().expanded)} Focused: {String(context().focused)} Disabled: {String(context().disabled)}
                    )}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title} {#snippet render(context)}
                    Expanded: {context().expanded} Focused: {context().focused} Disabled: {context().disabled}
                    {/snippet}
                    {item.content}
                    {/each}
                    ``` ## Guides ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes: ```css @keyframes slideDown { from { opacity: 0.01; height: 0; } to { opacity: 1; height: var(--height); } } @keyframes slideUp { from { opacity: 1; height: var(--height); } to { opacity: 0.01; height: 0; } } [data-scope='accordion'][data-part='item-content'][data-state='open'] { animation: slideDown 250ms ease-in-out; } [data-scope='accordion'][data-part='item-content'][data-state='closed'] { animation: slideUp 200ms ease-in-out; } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(value: string): string itemContent(value: string): string itemTrigger(value: string): string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `string[]` | No | The v-model value of the accordion | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AccordionApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionContext]>` | Yes | | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionItemContext]>` | Yes | | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focusedValue` | `string` | The value of the focused accordion item. | | `value` | `string[]` | The value of the accordion | | `setValue` | `(value: string[]) => void` | Sets the value of the accordion | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of an accordion item. | ## Accessibility This component complies with the [Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/). ### Keyboard Support **`Space`** Description: When focus is on an trigger of a collapsed item, the item is expanded **`Enter`** Description: When focus is on an trigger of a collapsed section, expands the section. **`Tab`** Description: Moves focus to the next focusable element **`Shift + Tab`** Description: Moves focus to the previous focusable element **`ArrowDown`** Description: Moves focus to the next trigger **`ArrowUp`** Description: Moves focus to the previous trigger. **`Home`** Description: When focus is on an trigger, moves focus to the first trigger. **`End`** Description: When focus is on an trigger, moves focus to the last trigger. # Accordion (VUE) ## Anatomy ```tsx ``` ## Examples ### Default Value Set the `defaultValue` prop to specify which item should be expanded by default. **Example: basic** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Controlled Use the `value` and `onValueChange` props to control the expanded items. **Example: controlled** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = useState([]) return ( setValue(details.value)}> {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = createSignal([]) return ( setValue(details.value)}> {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Root Provider An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Accordion, useAccordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion.value)} {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion, useAccordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion().value)} {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Value: {JSON.stringify(accordion().value)} {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Collapsible Use the `collapsible` prop to allow the user to collapse all panels. **Example: collapsible** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Multiple Use the `multiple` prop to allow multiple panels to be expanded simultaneously. **Example: multiple** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Horizontal By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout. **Example: horizontal** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Lazy Mount Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with `unmountOnExit` to unmount content when collapsed, freeing up resources. **Example: lazy-mount** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const LazyMount = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Context Use `Accordion.Context` or `useAccordionContext` to access the accordion state. **Example: context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context.value)}
                    context.focusedValue: {context.focusedValue || 'null'}
                    )}
                    {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    )}
                    {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(context)}
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    {/snippet}
                    {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Item State Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item. **Example: item-context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {items.map((item) => ( {item.title} {(context) => ( {context.expanded && Expanded} {context.focused && Focused} )}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {(item) => ( {item().title} {(context) => (
                    Expanded: {String(context().expanded)} Focused: {String(context().focused)} Disabled: {String(context().disabled)}
                    )}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title} {#snippet render(context)}
                    Expanded: {context().expanded} Focused: {context().focused} Disabled: {context().disabled}
                    {/snippet}
                    {item.content}
                    {/each}
                    ``` ## Guides ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes: ```css @keyframes slideDown { from { opacity: 0.01; height: 0; } to { opacity: 1; height: var(--height); } } @keyframes slideUp { from { opacity: 1; height: var(--height); } to { opacity: 0.01; height: 0; } } [data-scope='accordion'][data-part='item-content'][data-state='open'] { animation: slideDown 250ms ease-in-out; } [data-scope='accordion'][data-part='item-content'][data-state='closed'] { animation: slideUp 200ms ease-in-out; } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(value: string): string itemContent(value: string): string itemTrigger(value: string): string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `string[]` | No | The v-model value of the accordion | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AccordionApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionContext]>` | Yes | | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionItemContext]>` | Yes | | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focusedValue` | `string` | The value of the focused accordion item. | | `value` | `string[]` | The value of the accordion | | `setValue` | `(value: string[]) => void` | Sets the value of the accordion | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of an accordion item. | ## Accessibility This component complies with the [Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/). ### Keyboard Support **`Space`** Description: When focus is on an trigger of a collapsed item, the item is expanded **`Enter`** Description: When focus is on an trigger of a collapsed section, expands the section. **`Tab`** Description: Moves focus to the next focusable element **`Shift + Tab`** Description: Moves focus to the previous focusable element **`ArrowDown`** Description: Moves focus to the next trigger **`ArrowUp`** Description: Moves focus to the previous trigger. **`Home`** Description: When focus is on an trigger, moves focus to the first trigger. **`End`** Description: When focus is on an trigger, moves focus to the last trigger. # Accordion (SVELTE) ## Anatomy ```tsx ``` ## Examples ### Default Value Set the `defaultValue` prop to specify which item should be expanded by default. **Example: basic** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Controlled Use the `value` and `onValueChange` props to control the expanded items. **Example: controlled** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = useState([]) return ( setValue(details.value)}> {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = createSignal([]) return ( setValue(details.value)}> {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Root Provider An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Accordion, useAccordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion.value)} {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion, useAccordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion().value)} {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Value: {JSON.stringify(accordion().value)} {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Collapsible Use the `collapsible` prop to allow the user to collapse all panels. **Example: collapsible** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Multiple Use the `multiple` prop to allow multiple panels to be expanded simultaneously. **Example: multiple** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Horizontal By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout. **Example: horizontal** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Lazy Mount Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with `unmountOnExit` to unmount content when collapsed, freeing up resources. **Example: lazy-mount** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const LazyMount = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Context Use `Accordion.Context` or `useAccordionContext` to access the accordion state. **Example: context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context.value)}
                    context.focusedValue: {context.focusedValue || 'null'}
                    )}
                    {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    )}
                    {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(context)}
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    {/snippet}
                    {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Item State Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item. **Example: item-context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {items.map((item) => ( {item.title} {(context) => ( {context.expanded && Expanded} {context.focused && Focused} )}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {(item) => ( {item().title} {(context) => (
                    Expanded: {String(context().expanded)} Focused: {String(context().focused)} Disabled: {String(context().disabled)}
                    )}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title} {#snippet render(context)}
                    Expanded: {context().expanded} Focused: {context().focused} Disabled: {context().disabled}
                    {/snippet}
                    {item.content}
                    {/each}
                    ``` ## Guides ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes: ```css @keyframes slideDown { from { opacity: 0.01; height: 0; } to { opacity: 1; height: var(--height); } } @keyframes slideUp { from { opacity: 1; height: var(--height); } to { opacity: 0.01; height: 0; } } [data-scope='accordion'][data-part='item-content'][data-state='open'] { animation: slideDown 250ms ease-in-out; } [data-scope='accordion'][data-part='item-content'][data-state='closed'] { animation: slideUp 200ms ease-in-out; } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(value: string): string itemContent(value: string): string itemTrigger(value: string): string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `string[]` | No | The v-model value of the accordion | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AccordionApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionContext]>` | Yes | | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionItemContext]>` | Yes | | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focusedValue` | `string` | The value of the focused accordion item. | | `value` | `string[]` | The value of the accordion | | `setValue` | `(value: string[]) => void` | Sets the value of the accordion | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of an accordion item. | ## Accessibility This component complies with the [Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/). ### Keyboard Support **`Space`** Description: When focus is on an trigger of a collapsed item, the item is expanded **`Enter`** Description: When focus is on an trigger of a collapsed section, expands the section. **`Tab`** Description: Moves focus to the next focusable element **`Shift + Tab`** Description: Moves focus to the previous focusable element **`ArrowDown`** Description: Moves focus to the next trigger **`ArrowUp`** Description: Moves focus to the previous trigger. **`Home`** Description: When focus is on an trigger, moves focus to the first trigger. **`End`** Description: When focus is on an trigger, moves focus to the last trigger. # Accordion (SOLID) ## Anatomy ```tsx ``` ## Examples ### Default Value Set the `defaultValue` prop to specify which item should be expanded by default. **Example: basic** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Basic = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Controlled Use the `value` and `onValueChange` props to control the expanded items. **Example: controlled** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = useState([]) return ( setValue(details.value)}> {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/accordion.module.css' export const Controlled = () => { const [value, setValue] = createSignal([]) return ( setValue(details.value)}> {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Root Provider An alternative way to control the accordion is to use the `RootProvider` component and the `useAccordion` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Accordion, useAccordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion.value)} {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion, useAccordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const RootProvider = () => { const accordion = useAccordion({ multiple: true, defaultValue: ['ark-ui'], }) return (
                    Value: {JSON.stringify(accordion().value)} {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Value: {JSON.stringify(accordion().value)} {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Collapsible Use the `collapsible` prop to allow the user to collapse all panels. **Example: collapsible** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Collapsible = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Multiple Use the `multiple` prop to allow multiple panels to be expanded simultaneously. **Example: multiple** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Multiple = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Horizontal By default, the Accordion is oriented vertically. Use the `orientation` prop to switch to a horizontal layout. **Example: horizontal** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Horizontal = () => { return ( {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Lazy Mount Use the `lazyMount` prop to defer rendering of accordion content until the item is expanded. Combine with `unmountOnExit` to unmount content when collapsed, freeing up resources. **Example: lazy-mount** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const LazyMount = () => { return ( {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Context Use `Accordion.Context` or `useAccordionContext` to access the accordion state. **Example: context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import { ChevronDownIcon } from 'lucide-react' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context.value)}
                    context.focusedValue: {context.focusedValue || 'null'}
                    )}
                    {items.map((item) => ( {item.title}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const Context = () => { return ( {(context) => (
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    )}
                    {(item) => ( {item().title}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(context)}
                    context.value: {JSON.stringify(context().value)}
                    context.focusedValue: {context().focusedValue || 'null'}
                    {/snippet}
                    {#each items as item (item.value)} {item.title}
                    {item.content}
                    {/each}
                    ``` ### Item State Use `Accordion.ItemContext` or `useAccordionItemContext` to access the state of an accordion item. **Example: item-context** #### React ```tsx import { Accordion } from '@ark-ui/react/accordion' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {items.map((item) => ( {item.title} {(context) => ( {context.expanded && Expanded} {context.focused && Focused} )}
                    {item.content}
                    ))}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Solid ```tsx import { Accordion } from '@ark-ui/solid/accordion' import { ChevronDownIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/accordion.module.css' export const ItemContext = () => { return ( {(item) => ( {item().title} {(context) => (
                    Expanded: {String(context().expanded)} Focused: {String(context().focused)} Disabled: {String(context().disabled)}
                    )}
                    {item().content}
                    )}
                    ) } const items = [ { value: 'ark-ui', title: 'What is Ark UI?', content: 'A headless component library for building accessible web apps.', }, { value: 'getting-started', title: 'How to get started?', content: 'Install the package and import the components you need.', }, { value: 'maintainers', title: 'Who maintains this project?', content: 'Ark UI is maintained by the Chakra UI team.', }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.title} {#snippet render(context)}
                    Expanded: {context().expanded} Focused: {context().focused} Disabled: {context().disabled}
                    {/snippet}
                    {item.content}
                    {/each}
                    ``` ## Guides ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes: ```css @keyframes slideDown { from { opacity: 0.01; height: 0; } to { opacity: 1; height: var(--height); } } @keyframes slideUp { from { opacity: 1; height: var(--height); } to { opacity: 0.01; height: 0; } } [data-scope='accordion'][data-part='item-content'][data-state='open'] { animation: slideDown 250ms ease-in-out; } [data-scope='accordion'][data-part='item-content'][data-state='closed'] { animation: slideUp 200ms ease-in-out; } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(value: string): string itemContent(value: string): string itemTrigger(value: string): string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `string[]` | No | The v-model value of the accordion | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AccordionApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsible` | `boolean` | No | Whether an accordion item can be closed after it has been expanded. | | `defaultValue` | `string[]` | No | The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. | | `disabled` | `boolean` | No | Whether the accordion items are disabled | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (value: string) => string itemContent: (value: string) => string itemTrigger: (value: string) => string }>` | No | The ids of the elements in the accordion. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `multiple` | `boolean` | No | Whether multiple accordion items can be expanded at the same time. | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | The callback fired when the focused accordion item changes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback fired when the state of expanded/collapsed accordion items changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the accordion items. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the expanded accordion items. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | root | | `[data-orientation]` | The orientation of the accordion | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionContext]>` | Yes | | **ItemContent Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemContent Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-content | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAccordionItemContext]>` | Yes | | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | | `[data-orientation]` | The orientation of the item | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string` | Yes | The value of the accordion item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the accordion item is disabled. | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the item | **ItemTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | accordion | | `[data-part]` | item-trigger | | `[data-orientation]` | The orientation of the item | | `[data-state]` | "open" | "closed" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAccordionReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focusedValue` | `string` | The value of the focused accordion item. | | `value` | `string[]` | The value of the accordion | | `setValue` | `(value: string[]) => void` | Sets the value of the accordion | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of an accordion item. | ## Accessibility This component complies with the [Accordion WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/). ### Keyboard Support **`Space`** Description: When focus is on an trigger of a collapsed item, the item is expanded **`Enter`** Description: When focus is on an trigger of a collapsed section, expands the section. **`Tab`** Description: Moves focus to the next focusable element **`Shift + Tab`** Description: Moves focus to the previous focusable element **`ArrowDown`** Description: Moves focus to the next trigger **`ArrowUp`** Description: Moves focus to the previous trigger. **`Home`** Description: When focus is on an trigger, moves focus to the first trigger. **`End`** Description: When focus is on an trigger, moves focus to the last trigger. # Angle Slider (REACT) ## Anatomy ```tsx ``` ## Examples ### Basic Here's a basic example of the Angle Slider component. **Example: basic** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ### Controlled Use the `value` and `onValueChange` props to control the value of the Angle Slider. **Example: controlled** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import { useState } from 'react' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = useState(45) return ( setValue(e.value)}> Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For, createSignal } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = createSignal(45) return ( setValue(e.value)}> Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as markerValue} {/each} ``` ### Steps Use the `step` prop to set the discrete steps of the Angle Slider. **Example: step** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte 15 Step {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The aria-label of the slider. | | `aria-labelledby` | `string` | No | The aria-labelledby of the slider. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `getRootNode` | `() => ShadowRoot | Node | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `modelValue` | `number` | No | The v-model value of the angle slider | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AngleSliderApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `ref` | `Element` | No | | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAngleSliderContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `ref` | `Element` | No | | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `value` | `number` | The current value of the angle slider | | `valueAsDegree` | `string` | The current value as a degree string | | `setValue` | `(value: number) => void` | Sets the value of the angle slider | | `dragging` | `boolean` | Whether the slider is being dragged. | # Angle Slider (VUE) ## Anatomy ```tsx ``` ## Examples ### Basic Here's a basic example of the Angle Slider component. **Example: basic** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ### Controlled Use the `value` and `onValueChange` props to control the value of the Angle Slider. **Example: controlled** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import { useState } from 'react' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = useState(45) return ( setValue(e.value)}> Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For, createSignal } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = createSignal(45) return ( setValue(e.value)}> Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as markerValue} {/each} ``` ### Steps Use the `step` prop to set the discrete steps of the Angle Slider. **Example: step** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte 15 Step {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The aria-label of the slider. | | `aria-labelledby` | `string` | No | The aria-labelledby of the slider. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `getRootNode` | `() => ShadowRoot | Node | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `modelValue` | `number` | No | The v-model value of the angle slider | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AngleSliderApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `ref` | `Element` | No | | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAngleSliderContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `ref` | `Element` | No | | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `value` | `number` | The current value of the angle slider | | `valueAsDegree` | `string` | The current value as a degree string | | `setValue` | `(value: number) => void` | Sets the value of the angle slider | | `dragging` | `boolean` | Whether the slider is being dragged. | # Angle Slider (SVELTE) ## Anatomy ```tsx ``` ## Examples ### Basic Here's a basic example of the Angle Slider component. **Example: basic** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ### Controlled Use the `value` and `onValueChange` props to control the value of the Angle Slider. **Example: controlled** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import { useState } from 'react' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = useState(45) return ( setValue(e.value)}> Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For, createSignal } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = createSignal(45) return ( setValue(e.value)}> Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as markerValue} {/each} ``` ### Steps Use the `step` prop to set the discrete steps of the Angle Slider. **Example: step** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte 15 Step {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The aria-label of the slider. | | `aria-labelledby` | `string` | No | The aria-labelledby of the slider. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `getRootNode` | `() => ShadowRoot | Node | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `modelValue` | `number` | No | The v-model value of the angle slider | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AngleSliderApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `ref` | `Element` | No | | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAngleSliderContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `ref` | `Element` | No | | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `value` | `number` | The current value of the angle slider | | `valueAsDegree` | `string` | The current value as a degree string | | `setValue` | `(value: number) => void` | Sets the value of the angle slider | | `dragging` | `boolean` | Whether the slider is being dragged. | # Angle Slider (SOLID) ## Anatomy ```tsx ``` ## Examples ### Basic Here's a basic example of the Angle Slider component. **Example: basic** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Basic = () => { return ( Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ### Controlled Use the `value` and `onValueChange` props to control the value of the Angle Slider. **Example: controlled** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import { useState } from 'react' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = useState(45) return ( setValue(e.value)}> Rotation {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For, createSignal } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Controlled = () => { const [value, setValue] = createSignal(45) return ( setValue(e.value)}> Rotation {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Rotation {#each [0, 45, 90, 135, 180, 225, 270, 315] as markerValue} {/each} ``` ### Steps Use the `step` prop to set the discrete steps of the Angle Slider. **Example: step** #### React ```tsx import { AngleSlider } from '@ark-ui/react/angle-slider' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => ( ))} ) } ``` #### Solid ```tsx import { AngleSlider } from '@ark-ui/solid/angle-slider' import { For } from 'solid-js' import styles from 'styles/angle-slider.module.css' export const Step = () => { return ( 15 Step {(value) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte 15 Step {#each [0, 45, 90, 135, 180, 225, 270, 315] as value} {/each} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The aria-label of the slider. | | `aria-labelledby` | `string` | No | The aria-labelledby of the slider. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `dir` | `'ltr' | 'rtl'` | No | The document's text/writing direction. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `getRootNode` | `() => ShadowRoot | Node | Document` | No | A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `modelValue` | `number` | No | The v-model value of the angle slider | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `step` | `number` | No | The step value for the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AngleSliderApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `aria-label` | `string` | No | The accessible label for the slider thumb. | | `aria-labelledby` | `string` | No | The id of the element that labels the slider thumb. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `number` | No | The initial value of the slider. Use when you don't need to control the value of the slider. | | `disabled` | `boolean` | No | Whether the slider is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string thumb: string hiddenInput: string control: string valueText: string label: string }>` | No | The ids of the elements in the machine. Useful for composition. | | `invalid` | `boolean` | No | Whether the slider is invalid. | | `name` | `string` | No | The name of the slider. Useful for form submission. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | The callback function for when the value changes ends. | | `readOnly` | `boolean` | No | Whether the slider is read-only. | | `ref` | `Element` | No | | | `step` | `number` | No | The step value for the slider. | | `value` | `number` | No | The value of the slider. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | | `--angle` | The angle in degrees | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseAngleSliderContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **MarkerGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number` | Yes | The value of the marker | | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Marker Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | marker | | `[data-value]` | The value of the item | | `[data-state]` | | | `[data-disabled]` | Present when disabled | **Marker CSS Variables:** | Variable | Description | |----------|-------------| | `--marker-value` | The marker value value for the Marker | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAngleSliderReturn` | Yes | | | `ref` | `Element` | No | | **Thumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Thumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | angle-slider | | `[data-part]` | thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `value` | `number` | The current value of the angle slider | | `valueAsDegree` | `string` | The current value as a degree string | | `setValue` | `(value: number) => void` | Sets the value of the angle slider | | `dragging` | `boolean` | Whether the slider is being dragged. | # Avatar (REACT) ## Anatomy ```tsx ``` ## Examples ### Basic Display a user's profile image with a fallback. **Example: basic** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Vue ```vue ``` #### Svelte ```svelte PA ``` ### Events Use `onStatusChange` to listen for loading state changes. **Example: events** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import { useState } from 'react' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = useState('loading...') return (
                    Status: {status} setStatus(e.status)}> PA
                    ) } ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = createSignal('loading...') return (
                    Status: {status()} setStatus(e.status)}> PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Status: {status} (status = e.status)}> PA
                    ``` ### Root Provider An alternative way to control the avatar is to use the `RootProvider` component and the `useAvatar` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Avatar, useAvatar } from '@ark-ui/react/avatar' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = useState(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Solid ```tsx import { Avatar, useAvatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = createSignal(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    PA
                    ``` ## Guides ### Next.js Image Here's an example of how to use the `Image` component from `next/image`. ```tsx import { Avatar, useAvatarContext } from '@ark-ui/react/avatar' import { getImageProps, type ImageProps } from 'next/image' const AvatarNextImage = (props: ImageProps) => { const avatar = useAvatarContext() const { hidden, ...arkImageProps } = avatar.getImageProps() const nextImage = getImageProps(props) return ( ) } const Demo = () => { return ( JD ) } ``` > Refer to this [Github Discussion](https://github.com/chakra-ui/ark/discussions/3147) for more information. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'img'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AvatarApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | | `ref` | `Element` | No | | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'img'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `loaded` | `boolean` | Whether the image is loaded. | | `setSrc` | `(src: string) => void` | Function to set new src. | | `setLoaded` | `VoidFunction` | Function to set loaded state. | | `setError` | `VoidFunction` | Function to set error state. | # Avatar (VUE) ## Anatomy ```tsx ``` ## Examples ### Basic Display a user's profile image with a fallback. **Example: basic** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Vue ```vue ``` #### Svelte ```svelte PA ``` ### Events Use `onStatusChange` to listen for loading state changes. **Example: events** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import { useState } from 'react' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = useState('loading...') return (
                    Status: {status} setStatus(e.status)}> PA
                    ) } ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = createSignal('loading...') return (
                    Status: {status()} setStatus(e.status)}> PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Status: {status} (status = e.status)}> PA
                    ``` ### Root Provider An alternative way to control the avatar is to use the `RootProvider` component and the `useAvatar` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Avatar, useAvatar } from '@ark-ui/react/avatar' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = useState(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Solid ```tsx import { Avatar, useAvatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = createSignal(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    PA
                    ``` ## Guides ### Next.js Image Here's an example of how to use the `Image` component from `next/image`. ```tsx import { Avatar, useAvatarContext } from '@ark-ui/react/avatar' import { getImageProps, type ImageProps } from 'next/image' const AvatarNextImage = (props: ImageProps) => { const avatar = useAvatarContext() const { hidden, ...arkImageProps } = avatar.getImageProps() const nextImage = getImageProps(props) return ( ) } const Demo = () => { return ( JD ) } ``` > Refer to this [Github Discussion](https://github.com/chakra-ui/ark/discussions/3147) for more information. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'img'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AvatarApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | | `ref` | `Element` | No | | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'img'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `loaded` | `boolean` | Whether the image is loaded. | | `setSrc` | `(src: string) => void` | Function to set new src. | | `setLoaded` | `VoidFunction` | Function to set loaded state. | | `setError` | `VoidFunction` | Function to set error state. | # Avatar (SVELTE) ## Anatomy ```tsx ``` ## Examples ### Basic Display a user's profile image with a fallback. **Example: basic** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Vue ```vue ``` #### Svelte ```svelte PA ``` ### Events Use `onStatusChange` to listen for loading state changes. **Example: events** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import { useState } from 'react' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = useState('loading...') return (
                    Status: {status} setStatus(e.status)}> PA
                    ) } ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = createSignal('loading...') return (
                    Status: {status()} setStatus(e.status)}> PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Status: {status} (status = e.status)}> PA
                    ``` ### Root Provider An alternative way to control the avatar is to use the `RootProvider` component and the `useAvatar` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Avatar, useAvatar } from '@ark-ui/react/avatar' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = useState(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Solid ```tsx import { Avatar, useAvatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = createSignal(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    PA
                    ``` ## Guides ### Next.js Image Here's an example of how to use the `Image` component from `next/image`. ```tsx import { Avatar, useAvatarContext } from '@ark-ui/react/avatar' import { getImageProps, type ImageProps } from 'next/image' const AvatarNextImage = (props: ImageProps) => { const avatar = useAvatarContext() const { hidden, ...arkImageProps } = avatar.getImageProps() const nextImage = getImageProps(props) return ( ) } const Demo = () => { return ( JD ) } ``` > Refer to this [Github Discussion](https://github.com/chakra-ui/ark/discussions/3147) for more information. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'img'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AvatarApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | | `ref` | `Element` | No | | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'img'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `loaded` | `boolean` | Whether the image is loaded. | | `setSrc` | `(src: string) => void` | Function to set new src. | | `setLoaded` | `VoidFunction` | Function to set loaded state. | | `setError` | `VoidFunction` | Function to set error state. | # Avatar (SOLID) ## Anatomy ```tsx ``` ## Examples ### Basic Display a user's profile image with a fallback. **Example: basic** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import styles from 'styles/avatar.module.css' export const Basic = () => ( PA ) ``` #### Vue ```vue ``` #### Svelte ```svelte PA ``` ### Events Use `onStatusChange` to listen for loading state changes. **Example: events** #### React ```tsx import { Avatar } from '@ark-ui/react/avatar' import { useState } from 'react' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = useState('loading...') return (
                    Status: {status} setStatus(e.status)}> PA
                    ) } ``` #### Solid ```tsx import { Avatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import styles from 'styles/avatar.module.css' export const Events = () => { const [status, setStatus] = createSignal('loading...') return (
                    Status: {status()} setStatus(e.status)}> PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Status: {status} (status = e.status)}> PA
                    ``` ### Root Provider An alternative way to control the avatar is to use the `RootProvider` component and the `useAvatar` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Avatar, useAvatar } from '@ark-ui/react/avatar' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = useState(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Solid ```tsx import { Avatar, useAvatar } from '@ark-ui/solid/avatar' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/avatar.module.css' export const RootProvider = () => { const [count, setCount] = createSignal(0) const avatar = useAvatar() return (
                    PA
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    PA
                    ``` ## Guides ### Next.js Image Here's an example of how to use the `Image` component from `next/image`. ```tsx import { Avatar, useAvatarContext } from '@ark-ui/react/avatar' import { getImageProps, type ImageProps } from 'next/image' const AvatarNextImage = (props: ImageProps) => { const avatar = useAvatarContext() const { hidden, ...arkImageProps } = avatar.getImageProps() const nextImage = getImageProps(props) return ( ) } const Demo = () => { return ( JD ) } ``` > Refer to this [Github Discussion](https://github.com/chakra-ui/ark/discussions/3147) for more information. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'img'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `AvatarApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; image: string; fallback: string }>` | No | The ids of the elements in the avatar. Useful for composition. | | `onStatusChange` | `(details: StatusChangeDetails) => void` | No | Functional called when the image loading status changes. | | `ref` | `Element` | No | | **Fallback Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Fallback Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | fallback | | `[data-state]` | "hidden" | "visible" | **Image Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'img'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Image Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | avatar | | `[data-part]` | image | | `[data-state]` | "visible" | "hidden" | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseAvatarReturn` | Yes | | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `loaded` | `boolean` | Whether the image is loaded. | | `setSrc` | `(src: string) => void` | Function to set new src. | | `setLoaded` | `VoidFunction` | Function to set loaded state. | | `setError` | `VoidFunction` | Function to set error state. | # Carousel (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Controlled To create a controlled Carousel component, you can manage the state of the carousel using the `page` prop and update it when the `onPageChange` event handler is called: **Example: controlled** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = useState(0) return ( setPage(e.page)}> {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = createSignal(0) return ( setPage(details.page)} > {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Current page: {page}
                    {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Root Provider An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Carousel, useCarousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel.page} {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel, useCarousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel().page} {(image, index) => ( {image().alt} )} {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Page: {carousel().page} {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Autoplay Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically. **Example: autoplay** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {images.map((image, index) => ( {image.alt} ))} }> ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {(image, index) => ( {image().alt} )} }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#snippet fallback()}{/snippet} ``` ### Pause on Hover This feature isn't built-in, but you can use the `play()` and `pause()` methods from `Carousel.Context` to implement pause on hover. **Example: pause-on-hover** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {({ isPlaying }) => ( Autoplay is: {isPlaying ? 'playing' : 'paused'} )} {(api) => ( api.pause()} onPointerLeave={() => api.play()} > {images.map((image, index) => ( {image.alt} ))} )} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {(carousel) => ( Autoplay is: {carousel().isPlaying ? 'playing' : 'paused'} )} {(api) => ( api().pause()} onPointerLeave={() => api().play()} > {(image, index) => ( {image().alt} )} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Autoplay is: {api().isPlaying ? 'playing' : 'paused'} {/snippet} {#snippet render(api)} api().pause()} onpointerleave={() => api().play()} > {#each images as image, index} {image.alt} {/each} {/snippet} {#each images as _, index} {/each} ``` ### Thumbnail Indicators Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a visual preview of each slide: **Example: thumbnail-indicator** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((image, index) => ( {image.alt} ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {(image, index) => ( {image().alt} )} {(image, index) => ( {image().alt} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as image, index} {image.alt} {/each} ``` ### Vertical Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be helpful for displaying vertical galleries or content feeds. **Example: vertical** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Dynamic Manage slides dynamically by storing them in state and syncing the carousel page. Pass the `page` prop and `onPageChange` handler to `Carousel.Root`, and update `slideCount` when slides are added or removed. This demonstrates bidirectional state synchronization between your component state and the carousel. **Example: dynamic-slides** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = useState([0, 1, 2, 3, 4]) const [page, setPage] = useState(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {slides.map((slide, index) => (
                    Slide {slide + 1}
                    ))}
                    {slides.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = createSignal([0, 1, 2, 3, 4]) const [page, setPage] = createSignal(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {(slide, index) => (
                    Slide {slide() + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#each slides as slide, index}
                    Slide {slide + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Scroll to Slide Use `Carousel.Context` to access the carousel API and call `api.scrollToIndex(index)` to programmatically navigate to a specific slide. This is useful for creating custom navigation or jump-to-slide functionality. **Example: scroll-to** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const ScrollTo = () => { return ( {(api) => ( )} {Array.from({ length: 5 }, (_, index) => (
                    Slide {index + 1}
                    ))}
                    {Array.from({ length: 5 }, (_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const ScrollTo = () => { return ( {(api) => ( )} {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} {/snippet} {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Slides Per Page Display multiple slides simultaneously by setting the `slidesPerPage` prop on `Carousel.Root`. Use `api.pageSnapPoints` from `Carousel.Context` to render the correct number of indicators based on pages rather than individual slides. Add the `spacing` prop to control the gap between slides. **Example: slides-per-page** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' export const SlidesPerPage = () => { const slides = Array.from({ length: 6 }) return ( {slides.map((_, index) => (
                    Slide {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const SlidesPerPage = () => { return ( {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Spacing Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create layouts that show partial previews of adjacent slides. **Example: spacing** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {slides.map((_, index) => (
                    {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {(_, index) => (
                    {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte spacing='48px' {#each slides as _, index}
                    {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Variable Sizes To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to control where each one snaps into view. **Example: variable-size** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {items.map((item, index) => (
                    {item.label}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {(item, index) => (
                    {item.label}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item, index}
                    {item.label}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `paused` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is paused. | | `playing` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is playing. | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'center' | 'start' | 'end'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **ProgressText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(index: number): string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator(index: number): string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CarouselApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `ref` | `Element` | No | | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCarouselContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `page` | `number` | The current index of the carousel | | `pageSnapPoints` | `number[]` | The current snap points of the carousel | | `isPlaying` | `boolean` | Whether the carousel is auto playing | | `isDragging` | `boolean` | Whether the carousel is being dragged. This only works when `draggable` is true. | | `canScrollNext` | `boolean` | Whether the carousel is can scroll to the next view | | `canScrollPrev` | `boolean` | Whether the carousel is can scroll to the previous view | | `scrollToIndex` | `(index: number, instant?: boolean) => void` | Function to scroll to a specific item index | | `scrollTo` | `(page: number, instant?: boolean) => void` | Function to scroll to a specific page | | `scrollNext` | `(instant?: boolean) => void` | Function to scroll to the next page | | `scrollPrev` | `(instant?: boolean) => void` | Function to scroll to the previous page | | `getProgress` | `() => number` | Returns the current scroll progress as a percentage | | `getProgressText` | `() => string` | Returns the progress text | | `play` | `VoidFunction` | Function to start/resume autoplay | | `pause` | `VoidFunction` | Function to pause autoplay | | `isInView` | `(index: number) => boolean` | Whether the item is in view | | `refresh` | `VoidFunction` | Function to re-compute the snap points and clamp the page | ## Accessibility Complies with the [Carousel WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/). # Carousel (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Controlled To create a controlled Carousel component, you can manage the state of the carousel using the `page` prop and update it when the `onPageChange` event handler is called: **Example: controlled** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = useState(0) return ( setPage(e.page)}> {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = createSignal(0) return ( setPage(details.page)} > {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Current page: {page}
                    {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Root Provider An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Carousel, useCarousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel.page} {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel, useCarousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel().page} {(image, index) => ( {image().alt} )} {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Page: {carousel().page} {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Autoplay Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically. **Example: autoplay** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {images.map((image, index) => ( {image.alt} ))} }> ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {(image, index) => ( {image().alt} )} }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#snippet fallback()}{/snippet} ``` ### Pause on Hover This feature isn't built-in, but you can use the `play()` and `pause()` methods from `Carousel.Context` to implement pause on hover. **Example: pause-on-hover** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {({ isPlaying }) => ( Autoplay is: {isPlaying ? 'playing' : 'paused'} )} {(api) => ( api.pause()} onPointerLeave={() => api.play()} > {images.map((image, index) => ( {image.alt} ))} )} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {(carousel) => ( Autoplay is: {carousel().isPlaying ? 'playing' : 'paused'} )} {(api) => ( api().pause()} onPointerLeave={() => api().play()} > {(image, index) => ( {image().alt} )} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Autoplay is: {api().isPlaying ? 'playing' : 'paused'} {/snippet} {#snippet render(api)} api().pause()} onpointerleave={() => api().play()} > {#each images as image, index} {image.alt} {/each} {/snippet} {#each images as _, index} {/each} ``` ### Thumbnail Indicators Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a visual preview of each slide: **Example: thumbnail-indicator** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((image, index) => ( {image.alt} ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {(image, index) => ( {image().alt} )} {(image, index) => ( {image().alt} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as image, index} {image.alt} {/each} ``` ### Vertical Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be helpful for displaying vertical galleries or content feeds. **Example: vertical** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Dynamic Manage slides dynamically by storing them in state and syncing the carousel page. Pass the `page` prop and `onPageChange` handler to `Carousel.Root`, and update `slideCount` when slides are added or removed. This demonstrates bidirectional state synchronization between your component state and the carousel. **Example: dynamic-slides** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = useState([0, 1, 2, 3, 4]) const [page, setPage] = useState(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {slides.map((slide, index) => (
                    Slide {slide + 1}
                    ))}
                    {slides.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = createSignal([0, 1, 2, 3, 4]) const [page, setPage] = createSignal(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {(slide, index) => (
                    Slide {slide() + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#each slides as slide, index}
                    Slide {slide + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Scroll to Slide Use `Carousel.Context` to access the carousel API and call `api.scrollToIndex(index)` to programmatically navigate to a specific slide. This is useful for creating custom navigation or jump-to-slide functionality. **Example: scroll-to** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const ScrollTo = () => { return ( {(api) => ( )} {Array.from({ length: 5 }, (_, index) => (
                    Slide {index + 1}
                    ))}
                    {Array.from({ length: 5 }, (_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const ScrollTo = () => { return ( {(api) => ( )} {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} {/snippet} {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Slides Per Page Display multiple slides simultaneously by setting the `slidesPerPage` prop on `Carousel.Root`. Use `api.pageSnapPoints` from `Carousel.Context` to render the correct number of indicators based on pages rather than individual slides. Add the `spacing` prop to control the gap between slides. **Example: slides-per-page** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' export const SlidesPerPage = () => { const slides = Array.from({ length: 6 }) return ( {slides.map((_, index) => (
                    Slide {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const SlidesPerPage = () => { return ( {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Spacing Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create layouts that show partial previews of adjacent slides. **Example: spacing** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {slides.map((_, index) => (
                    {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {(_, index) => (
                    {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte spacing='48px' {#each slides as _, index}
                    {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Variable Sizes To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to control where each one snaps into view. **Example: variable-size** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {items.map((item, index) => (
                    {item.label}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {(item, index) => (
                    {item.label}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item, index}
                    {item.label}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `paused` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is paused. | | `playing` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is playing. | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'center' | 'start' | 'end'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **ProgressText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(index: number): string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator(index: number): string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CarouselApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `ref` | `Element` | No | | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCarouselContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `page` | `number` | The current index of the carousel | | `pageSnapPoints` | `number[]` | The current snap points of the carousel | | `isPlaying` | `boolean` | Whether the carousel is auto playing | | `isDragging` | `boolean` | Whether the carousel is being dragged. This only works when `draggable` is true. | | `canScrollNext` | `boolean` | Whether the carousel is can scroll to the next view | | `canScrollPrev` | `boolean` | Whether the carousel is can scroll to the previous view | | `scrollToIndex` | `(index: number, instant?: boolean) => void` | Function to scroll to a specific item index | | `scrollTo` | `(page: number, instant?: boolean) => void` | Function to scroll to a specific page | | `scrollNext` | `(instant?: boolean) => void` | Function to scroll to the next page | | `scrollPrev` | `(instant?: boolean) => void` | Function to scroll to the previous page | | `getProgress` | `() => number` | Returns the current scroll progress as a percentage | | `getProgressText` | `() => string` | Returns the progress text | | `play` | `VoidFunction` | Function to start/resume autoplay | | `pause` | `VoidFunction` | Function to pause autoplay | | `isInView` | `(index: number) => boolean` | Whether the item is in view | | `refresh` | `VoidFunction` | Function to re-compute the snap points and clamp the page | ## Accessibility Complies with the [Carousel WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/). # Carousel (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Controlled To create a controlled Carousel component, you can manage the state of the carousel using the `page` prop and update it when the `onPageChange` event handler is called: **Example: controlled** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = useState(0) return ( setPage(e.page)}> {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = createSignal(0) return ( setPage(details.page)} > {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Current page: {page}
                    {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Root Provider An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Carousel, useCarousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel.page} {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel, useCarousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel().page} {(image, index) => ( {image().alt} )} {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Page: {carousel().page} {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Autoplay Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically. **Example: autoplay** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {images.map((image, index) => ( {image.alt} ))} }> ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {(image, index) => ( {image().alt} )} }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#snippet fallback()}{/snippet} ``` ### Pause on Hover This feature isn't built-in, but you can use the `play()` and `pause()` methods from `Carousel.Context` to implement pause on hover. **Example: pause-on-hover** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {({ isPlaying }) => ( Autoplay is: {isPlaying ? 'playing' : 'paused'} )} {(api) => ( api.pause()} onPointerLeave={() => api.play()} > {images.map((image, index) => ( {image.alt} ))} )} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {(carousel) => ( Autoplay is: {carousel().isPlaying ? 'playing' : 'paused'} )} {(api) => ( api().pause()} onPointerLeave={() => api().play()} > {(image, index) => ( {image().alt} )} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Autoplay is: {api().isPlaying ? 'playing' : 'paused'} {/snippet} {#snippet render(api)} api().pause()} onpointerleave={() => api().play()} > {#each images as image, index} {image.alt} {/each} {/snippet} {#each images as _, index} {/each} ``` ### Thumbnail Indicators Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a visual preview of each slide: **Example: thumbnail-indicator** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((image, index) => ( {image.alt} ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {(image, index) => ( {image().alt} )} {(image, index) => ( {image().alt} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as image, index} {image.alt} {/each} ``` ### Vertical Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be helpful for displaying vertical galleries or content feeds. **Example: vertical** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Dynamic Manage slides dynamically by storing them in state and syncing the carousel page. Pass the `page` prop and `onPageChange` handler to `Carousel.Root`, and update `slideCount` when slides are added or removed. This demonstrates bidirectional state synchronization between your component state and the carousel. **Example: dynamic-slides** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = useState([0, 1, 2, 3, 4]) const [page, setPage] = useState(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {slides.map((slide, index) => (
                    Slide {slide + 1}
                    ))}
                    {slides.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = createSignal([0, 1, 2, 3, 4]) const [page, setPage] = createSignal(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {(slide, index) => (
                    Slide {slide() + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#each slides as slide, index}
                    Slide {slide + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Scroll to Slide Use `Carousel.Context` to access the carousel API and call `api.scrollToIndex(index)` to programmatically navigate to a specific slide. This is useful for creating custom navigation or jump-to-slide functionality. **Example: scroll-to** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const ScrollTo = () => { return ( {(api) => ( )} {Array.from({ length: 5 }, (_, index) => (
                    Slide {index + 1}
                    ))}
                    {Array.from({ length: 5 }, (_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const ScrollTo = () => { return ( {(api) => ( )} {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} {/snippet} {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Slides Per Page Display multiple slides simultaneously by setting the `slidesPerPage` prop on `Carousel.Root`. Use `api.pageSnapPoints` from `Carousel.Context` to render the correct number of indicators based on pages rather than individual slides. Add the `spacing` prop to control the gap between slides. **Example: slides-per-page** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' export const SlidesPerPage = () => { const slides = Array.from({ length: 6 }) return ( {slides.map((_, index) => (
                    Slide {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const SlidesPerPage = () => { return ( {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Spacing Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create layouts that show partial previews of adjacent slides. **Example: spacing** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {slides.map((_, index) => (
                    {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {(_, index) => (
                    {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte spacing='48px' {#each slides as _, index}
                    {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Variable Sizes To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to control where each one snaps into view. **Example: variable-size** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {items.map((item, index) => (
                    {item.label}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {(item, index) => (
                    {item.label}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item, index}
                    {item.label}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `paused` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is paused. | | `playing` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is playing. | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'center' | 'start' | 'end'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **ProgressText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(index: number): string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator(index: number): string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CarouselApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `ref` | `Element` | No | | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCarouselContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `page` | `number` | The current index of the carousel | | `pageSnapPoints` | `number[]` | The current snap points of the carousel | | `isPlaying` | `boolean` | Whether the carousel is auto playing | | `isDragging` | `boolean` | Whether the carousel is being dragged. This only works when `draggable` is true. | | `canScrollNext` | `boolean` | Whether the carousel is can scroll to the next view | | `canScrollPrev` | `boolean` | Whether the carousel is can scroll to the previous view | | `scrollToIndex` | `(index: number, instant?: boolean) => void` | Function to scroll to a specific item index | | `scrollTo` | `(page: number, instant?: boolean) => void` | Function to scroll to a specific page | | `scrollNext` | `(instant?: boolean) => void` | Function to scroll to the next page | | `scrollPrev` | `(instant?: boolean) => void` | Function to scroll to the previous page | | `getProgress` | `() => number` | Returns the current scroll progress as a percentage | | `getProgressText` | `() => string` | Returns the progress text | | `play` | `VoidFunction` | Function to start/resume autoplay | | `pause` | `VoidFunction` | Function to pause autoplay | | `isInView` | `(index: number) => boolean` | Whether the item is in view | | `refresh` | `VoidFunction` | Function to re-compute the snap points and clamp the page | ## Accessibility Complies with the [Carousel WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/). # Carousel (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Basic = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Controlled To create a controlled Carousel component, you can manage the state of the carousel using the `page` prop and update it when the `onPageChange` event handler is called: **Example: controlled** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = useState(0) return ( setPage(e.page)}> {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Controlled = () => { const [page, setPage] = createSignal(0) return ( setPage(details.page)} > {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Current page: {page}
                    {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Root Provider An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Carousel, useCarousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel.page} {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel, useCarousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const RootProvider = () => { const carousel = useCarousel({ slideCount: images.length }) return (
                    Page: {carousel().page} {(image, index) => ( {image().alt} )} {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Page: {carousel().page} {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each}
                    ``` ### Autoplay Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically. **Example: autoplay** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {images.map((image, index) => ( {image.alt} ))} }> ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ChevronLeftIcon, ChevronRightIcon, PauseIcon, PlayIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Autoplay = () => { return ( {(image, index) => ( {image().alt} )} }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#snippet fallback()}{/snippet} ``` ### Pause on Hover This feature isn't built-in, but you can use the `play()` and `pause()` methods from `Carousel.Context` to implement pause on hover. **Example: pause-on-hover** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {({ isPlaying }) => ( Autoplay is: {isPlaying ? 'playing' : 'paused'} )} {(api) => ( api.pause()} onPointerLeave={() => api.play()} > {images.map((image, index) => ( {image.alt} ))} )} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const PauseOnHover = () => { return ( {(carousel) => ( Autoplay is: {carousel().isPlaying ? 'playing' : 'paused'} )} {(api) => ( api().pause()} onPointerLeave={() => api().play()} > {(image, index) => ( {image().alt} )} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Autoplay is: {api().isPlaying ? 'playing' : 'paused'} {/snippet} {#snippet render(api)} api().pause()} onpointerleave={() => api().play()} > {#each images as image, index} {image.alt} {/each} {/snippet} {#each images as _, index} {/each} ``` ### Thumbnail Indicators Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a visual preview of each slide: **Example: thumbnail-indicator** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((image, index) => ( {image.alt} ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const ThumbnailIndicator = () => { return ( {(image, index) => ( {image().alt} )} {(image, index) => ( {image().alt} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as image, index} {image.alt} {/each} ``` ### Vertical Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be helpful for displaying vertical galleries or content feeds. **Example: vertical** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {images.map((image, index) => ( {image.alt} ))} {images.map((_, index) => ( ))} ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowDownIcon, ArrowUpIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const images = [ { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape' }, { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline' }, { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view' }, { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset' }, { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path' }, ] export const Vertical = () => { return ( {(image, index) => ( {image().alt} )} {(_, index) => } ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each images as image, index} {image.alt} {/each} {#each images as _, index} {/each} ``` ### Dynamic Manage slides dynamically by storing them in state and syncing the carousel page. Pass the `page` prop and `onPageChange` handler to `Carousel.Root`, and update `slideCount` when slides are added or removed. This demonstrates bidirectional state synchronization between your component state and the carousel. **Example: dynamic-slides** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = useState([0, 1, 2, 3, 4]) const [page, setPage] = useState(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {slides.map((slide, index) => (
                    Slide {slide + 1}
                    ))}
                    {slides.map((_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon, PlusIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const DynamicSlides = () => { const [slides, setSlides] = createSignal([0, 1, 2, 3, 4]) const [page, setPage] = createSignal(0) const addSlide = () => { setSlides((prevSlides) => { const max = Math.max(...prevSlides) return [...prevSlides, max + 1] }) } return (
                    setPage(details.page)} > {(slide, index) => (
                    Slide {slide() + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    {#each slides as slide, index}
                    Slide {slide + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Scroll to Slide Use `Carousel.Context` to access the carousel API and call `api.scrollToIndex(index)` to programmatically navigate to a specific slide. This is useful for creating custom navigation or jump-to-slide functionality. **Example: scroll-to** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' export const ScrollTo = () => { return ( {(api) => ( )} {Array.from({ length: 5 }, (_, index) => (
                    Slide {index + 1}
                    ))}
                    {Array.from({ length: 5 }, (_, index) => ( ))}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const ScrollTo = () => { return ( {(api) => ( )} {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(_, index) => }
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} {/snippet} {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#each slides as _, index} {/each}
                    ``` ### Slides Per Page Display multiple slides simultaneously by setting the `slidesPerPage` prop on `Carousel.Root`. Use `api.pageSnapPoints` from `Carousel.Context` to render the correct number of indicators based on pages rather than individual slides. Add the `spacing` prop to control the gap between slides. **Example: slides-per-page** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' export const SlidesPerPage = () => { const slides = Array.from({ length: 6 }) return ( {slides.map((_, index) => (
                    Slide {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const SlidesPerPage = () => { return ( {(_, index) => (
                    Slide {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each slides as _, index}
                    Slide {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Spacing Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create layouts that show partial previews of adjacent slides. **Example: spacing** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {slides.map((_, index) => (
                    {index + 1}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/carousel.module.css' const slides = Array.from({ length: 6 }) export const Spacing = () => { return ( spacing='48px' {(_, index) => (
                    {index + 1}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte spacing='48px' {#each slides as _, index}
                    {index + 1}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ### Variable Sizes To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to control where each one snaps into view. **Example: variable-size** #### React ```tsx import { Carousel } from '@ark-ui/react/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {items.map((item, index) => (
                    {item.label}
                    ))}
                    {(api) => ( {api.pageSnapPoints.map((_, index) => ( ))} )}
                    ) } ``` #### Solid ```tsx import { Carousel } from '@ark-ui/solid/carousel' import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/carousel.module.css' const items = [ { id: '1', width: '120px', label: 'Small' }, { id: '2', width: '200px', label: 'Medium Size' }, { id: '3', width: '80px', label: 'XS' }, { id: '4', width: '250px', label: 'Large Content Here' }, { id: '5', width: '150px', label: 'Regular' }, ] export const VariableSize = () => { return ( {(item, index) => (
                    {item.label}
                    )}
                    {(api) => ( {(_, index) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item, index}
                    {item.label}
                    {/each}
                    {#snippet render(api)} {#each api().pageSnapPoints as _, index} {/each} {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `paused` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is paused. | | `playing` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | The content to render when autoplay is playing. | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'center' | 'start' | 'end'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **ProgressText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item(index: number): string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator(index: number): string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CarouselApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `slideCount` | `number` | Yes | The total number of slides. Useful for SSR to render the initial ating the snap points. | | `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. | | `defaultPage` | `number` | No | The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string item: (index: number) => string itemGroup: string nextTrigger: string prevTrigger: string indicatorGroup: string indicator: (index: number) => string }>` | No | The ids of the elements in the carousel. Useful for composition. | | `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. | | `loop` | `boolean` | No | Whether the carousel should loop around. | | `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. | | `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. | | `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. | | `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. | | `padding` | `string` | No | Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | | `page` | `number` | No | The controlled page of the carousel. | | `ref` | `Element` | No | | | `slidesPerMove` | `number | 'auto'` | No | The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. | | `slidesPerPage` | `number` | No | The number of slides to show at a time. | | `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. | | `spacing` | `string` | No | The amount of space between items. | | `translations` | `IntlTranslations` | No | The localized messages to use. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | root | | `[data-orientation]` | The orientation of the carousel | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--slides-per-page` | The number of slides visible per page | | `--slide-spacing` | The spacing between slides | | `--slide-item-size` | The calculated size of each slide item | **AutoplayTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AutoplayTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | autoplay-trigger | | `[data-orientation]` | The orientation of the autoplaytrigger | | `[data-pressed]` | Present when pressed | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCarouselContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | control | | `[data-orientation]` | The orientation of the control | **IndicatorGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **IndicatorGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator-group | | `[data-orientation]` | The orientation of the indicatorgroup | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the indicator. | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `readOnly` | `boolean` | No | Whether the indicator is read only. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | indicator | | `[data-orientation]` | The orientation of the indicator | | `[data-index]` | The index of the item | | `[data-readonly]` | Present when read-only | | `[data-current]` | Present when current | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item-group | | `[data-orientation]` | The orientation of the item | | `[data-dragging]` | Present when in the dragging state | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `index` | `number` | Yes | The index of the item. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `snapAlign` | `'start' | 'end' | 'center'` | No | The snap alignment of the item. | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | item | | `[data-index]` | The index of the item | | `[data-inview]` | Present when in viewport | | `[data-orientation]` | The orientation of the item | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | next-trigger | | `[data-orientation]` | The orientation of the nexttrigger | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | carousel | | `[data-part]` | prev-trigger | | `[data-orientation]` | The orientation of the prevtrigger | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCarouselReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `page` | `number` | The current index of the carousel | | `pageSnapPoints` | `number[]` | The current snap points of the carousel | | `isPlaying` | `boolean` | Whether the carousel is auto playing | | `isDragging` | `boolean` | Whether the carousel is being dragged. This only works when `draggable` is true. | | `canScrollNext` | `boolean` | Whether the carousel is can scroll to the next view | | `canScrollPrev` | `boolean` | Whether the carousel is can scroll to the previous view | | `scrollToIndex` | `(index: number, instant?: boolean) => void` | Function to scroll to a specific item index | | `scrollTo` | `(page: number, instant?: boolean) => void` | Function to scroll to a specific page | | `scrollNext` | `(instant?: boolean) => void` | Function to scroll to the next page | | `scrollPrev` | `(instant?: boolean) => void` | Function to scroll to the previous page | | `getProgress` | `() => number` | Returns the current scroll progress as a percentage | | `getProgressText` | `() => string` | Returns the progress text | | `play` | `VoidFunction` | Function to start/resume autoplay | | `pause` | `VoidFunction` | Function to pause autoplay | | `isInView` | `(index: number) => boolean` | Whether the item is in view | | `refresh` | `VoidFunction` | Function to re-compute the snap points and clamp the page | ## Accessibility Complies with the [Carousel WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/). # Checkbox (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Default Checked Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally. **Example: default-checked** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Controlled Use the `checked` and `onCheckedChange` props to programatically control the checkbox's state. **Example: controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = useState(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = createSignal(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Root Provider An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Checkbox, useCheckbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox.checked ? ( ) : ( )}
                    ) } ``` #### Solid ```tsx import { Checkbox, useCheckbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox().checked ? ( ) : ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Checkbox {#if checkbox().checked} {:else} {/if}
                    ``` ### Disabled Use the `disabled` prop to make the checkbox non-interactive. **Example: disabled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Indeterminate Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked). **Example: indeterminate** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Field The checkbox integrates smoothly with the `Field` component to handle form state, helper text, and error text for proper accessibility. **Example: with-field** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Field } from '@ark-ui/react/field' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Field } from '@ark-ui/solid/field' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label Additional Info Error Info ``` ### Form Pass the `name` and `value` props to the `Checkbox.Root` component to make the checkbox part of a form. The checkbox's value will be submitted with the form when the user submits it. **Example: with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ``` ### Context Access the checkbox's state and methods with `Checkbox.Context` or the `useCheckboxContext` hook. **Example: context** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox.checked)}} ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox().checked)}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Checked: {String(api().checked)} {/snippet} ``` ### Group Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values. **Example: group** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Group = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Group = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Controlled Group Use the `value` and `onValueChange` props to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection. **Example: group-controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = useState(['react']) return (
                    value: {JSON.stringify(value)} {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = createSignal(['react']) return (
                    value: {JSON.stringify(value())} {(item) => ( {item.label} )}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {JSON.stringify(value)} {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Group Provider Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes. **Example: group-provider** #### React ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {items.map((item) => ( {item.label} ))} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {(item) => ( {item.label} )} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Invalid Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group. **Example: group-with-invalid** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Select All Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected. **Example: group-with-select-all** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => { return ( {props.children} ) } export const GroupWithSelectAll = () => { const [value, setValue] = useState([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = value.length === items.length const indeterminate = value.length > 0 && value.length < items.length return (
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import { For, createSignal, createMemo } from 'solid-js' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => ( {props.children} ) export const GroupWithSelectAll = () => { const [value, setValue] = createSignal([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = createMemo(() => value().length === items.length) const indeterminate = createMemo(() => value().length > 0 && value().length < items.length) return (
                    Selected: {JSON.stringify(value())} handleSelectAll(!!details.checked)} > JSX Frameworks {(item) => {item.label}}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet CheckboxItem(item: (typeof items)[number])} {item.label} {/snippet}
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {#each items as item (item.value)} {@render CheckboxItem(item)} {/each}
                    ``` ### Group Form Use the `Checkbox.Group` component within a form to handle multiple checkbox values with form submission. The `name` prop ensures all selected values are collected as an array when the form is submitted using `FormData.getAll()`. **Example: group-with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {items.map((item) => ( {item.label} ))}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {(item) => ( {item.label} )}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Fieldset Use the `Fieldset` component with `Checkbox.Group` to provide semantic grouping with legend, helper text, and error text support. **Example: group-with-fieldset** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Fieldset } from '@ark-ui/react/fieldset' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Fieldset } from '@ark-ui/solid/fieldset' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Select frameworks Choose your preferred frameworks {#each items as item (item.value)} {item.label} {/each} ``` ## Guides ### asChild Behavior The `Checkbox.Root` element of the checkbox is a `label` element. This is because the checkbox is a form control and should be associated with a label to provide context and meaning to the user. Otherwise, the HTML and accessibility structure will be invalid. > If you need to use the `asChild` property, make sure that the `label` element is the direct child of the > `Checkbox.Root` component. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[] | Accessor` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `Accessor` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `modelValue` | `string[]` | No | The controlled value of the checkbox group | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `{ isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean | undefined; readOnly: boolean | undefined; invalid: boolean | undefined; addValue: (val: string) => void; setValue: (value: string[]) => void; toggleValue: (val: string) => void; getItemProps: (itemProps:...` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CheckboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCheckboxReturn]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `ref` | `Element` | No | | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `() => { isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean; readOnly: boolean; invalid: boolean; setValue: (newValue: string[]) => void; addValue: (val: string) => void; toggleValue: (val: string) => void; getItemProps: (itemProps: CheckboxGroupItemProps) =>...` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `checked` | `boolean` | Whether the checkbox is checked | | `disabled` | `boolean` | Whether the checkbox is disabled | | `indeterminate` | `boolean` | Whether the checkbox is indeterminate | | `focused` | `boolean` | Whether the checkbox is focused | | `checkedState` | `CheckedState` | The checked state of the checkbox | | `setChecked` | `(checked: CheckedState) => void` | Function to set the checked state of the checkbox | | `toggleChecked` | `VoidFunction` | Function to toggle the checked state of the checkbox | ## Accessibility Complies with the [Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). ### Keyboard Support **`Space`** Description: Toggle the checkbox # Checkbox (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Default Checked Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally. **Example: default-checked** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Controlled Use the `checked` and `onCheckedChange` props to programatically control the checkbox's state. **Example: controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = useState(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = createSignal(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Root Provider An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Checkbox, useCheckbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox.checked ? ( ) : ( )}
                    ) } ``` #### Solid ```tsx import { Checkbox, useCheckbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox().checked ? ( ) : ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Checkbox {#if checkbox().checked} {:else} {/if}
                    ``` ### Disabled Use the `disabled` prop to make the checkbox non-interactive. **Example: disabled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Indeterminate Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked). **Example: indeterminate** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Field The checkbox integrates smoothly with the `Field` component to handle form state, helper text, and error text for proper accessibility. **Example: with-field** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Field } from '@ark-ui/react/field' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Field } from '@ark-ui/solid/field' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label Additional Info Error Info ``` ### Form Pass the `name` and `value` props to the `Checkbox.Root` component to make the checkbox part of a form. The checkbox's value will be submitted with the form when the user submits it. **Example: with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ``` ### Context Access the checkbox's state and methods with `Checkbox.Context` or the `useCheckboxContext` hook. **Example: context** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox.checked)}} ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox().checked)}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Checked: {String(api().checked)} {/snippet} ``` ### Group Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values. **Example: group** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Group = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Group = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Controlled Group Use the `value` and `onValueChange` props to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection. **Example: group-controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = useState(['react']) return (
                    value: {JSON.stringify(value)} {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = createSignal(['react']) return (
                    value: {JSON.stringify(value())} {(item) => ( {item.label} )}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {JSON.stringify(value)} {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Group Provider Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes. **Example: group-provider** #### React ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {items.map((item) => ( {item.label} ))} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {(item) => ( {item.label} )} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Invalid Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group. **Example: group-with-invalid** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Select All Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected. **Example: group-with-select-all** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => { return ( {props.children} ) } export const GroupWithSelectAll = () => { const [value, setValue] = useState([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = value.length === items.length const indeterminate = value.length > 0 && value.length < items.length return (
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import { For, createSignal, createMemo } from 'solid-js' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => ( {props.children} ) export const GroupWithSelectAll = () => { const [value, setValue] = createSignal([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = createMemo(() => value().length === items.length) const indeterminate = createMemo(() => value().length > 0 && value().length < items.length) return (
                    Selected: {JSON.stringify(value())} handleSelectAll(!!details.checked)} > JSX Frameworks {(item) => {item.label}}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet CheckboxItem(item: (typeof items)[number])} {item.label} {/snippet}
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {#each items as item (item.value)} {@render CheckboxItem(item)} {/each}
                    ``` ### Group Form Use the `Checkbox.Group` component within a form to handle multiple checkbox values with form submission. The `name` prop ensures all selected values are collected as an array when the form is submitted using `FormData.getAll()`. **Example: group-with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {items.map((item) => ( {item.label} ))}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {(item) => ( {item.label} )}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Fieldset Use the `Fieldset` component with `Checkbox.Group` to provide semantic grouping with legend, helper text, and error text support. **Example: group-with-fieldset** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Fieldset } from '@ark-ui/react/fieldset' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Fieldset } from '@ark-ui/solid/fieldset' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Select frameworks Choose your preferred frameworks {#each items as item (item.value)} {item.label} {/each} ``` ## Guides ### asChild Behavior The `Checkbox.Root` element of the checkbox is a `label` element. This is because the checkbox is a form control and should be associated with a label to provide context and meaning to the user. Otherwise, the HTML and accessibility structure will be invalid. > If you need to use the `asChild` property, make sure that the `label` element is the direct child of the > `Checkbox.Root` component. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[] | Accessor` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `Accessor` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `modelValue` | `string[]` | No | The controlled value of the checkbox group | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `{ isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean | undefined; readOnly: boolean | undefined; invalid: boolean | undefined; addValue: (val: string) => void; setValue: (value: string[]) => void; toggleValue: (val: string) => void; getItemProps: (itemProps:...` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CheckboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCheckboxReturn]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `ref` | `Element` | No | | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `() => { isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean; readOnly: boolean; invalid: boolean; setValue: (newValue: string[]) => void; addValue: (val: string) => void; toggleValue: (val: string) => void; getItemProps: (itemProps: CheckboxGroupItemProps) =>...` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `checked` | `boolean` | Whether the checkbox is checked | | `disabled` | `boolean` | Whether the checkbox is disabled | | `indeterminate` | `boolean` | Whether the checkbox is indeterminate | | `focused` | `boolean` | Whether the checkbox is focused | | `checkedState` | `CheckedState` | The checked state of the checkbox | | `setChecked` | `(checked: CheckedState) => void` | Function to set the checked state of the checkbox | | `toggleChecked` | `VoidFunction` | Function to toggle the checked state of the checkbox | ## Accessibility Complies with the [Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). ### Keyboard Support **`Space`** Description: Toggle the checkbox # Checkbox (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Default Checked Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally. **Example: default-checked** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Controlled Use the `checked` and `onCheckedChange` props to programatically control the checkbox's state. **Example: controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = useState(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = createSignal(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Root Provider An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Checkbox, useCheckbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox.checked ? ( ) : ( )}
                    ) } ``` #### Solid ```tsx import { Checkbox, useCheckbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox().checked ? ( ) : ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Checkbox {#if checkbox().checked} {:else} {/if}
                    ``` ### Disabled Use the `disabled` prop to make the checkbox non-interactive. **Example: disabled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Indeterminate Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked). **Example: indeterminate** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Field The checkbox integrates smoothly with the `Field` component to handle form state, helper text, and error text for proper accessibility. **Example: with-field** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Field } from '@ark-ui/react/field' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Field } from '@ark-ui/solid/field' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label Additional Info Error Info ``` ### Form Pass the `name` and `value` props to the `Checkbox.Root` component to make the checkbox part of a form. The checkbox's value will be submitted with the form when the user submits it. **Example: with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ``` ### Context Access the checkbox's state and methods with `Checkbox.Context` or the `useCheckboxContext` hook. **Example: context** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox.checked)}} ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox().checked)}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Checked: {String(api().checked)} {/snippet} ``` ### Group Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values. **Example: group** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Group = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Group = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Controlled Group Use the `value` and `onValueChange` props to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection. **Example: group-controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = useState(['react']) return (
                    value: {JSON.stringify(value)} {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = createSignal(['react']) return (
                    value: {JSON.stringify(value())} {(item) => ( {item.label} )}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {JSON.stringify(value)} {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Group Provider Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes. **Example: group-provider** #### React ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {items.map((item) => ( {item.label} ))} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {(item) => ( {item.label} )} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Invalid Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group. **Example: group-with-invalid** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Select All Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected. **Example: group-with-select-all** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => { return ( {props.children} ) } export const GroupWithSelectAll = () => { const [value, setValue] = useState([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = value.length === items.length const indeterminate = value.length > 0 && value.length < items.length return (
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import { For, createSignal, createMemo } from 'solid-js' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => ( {props.children} ) export const GroupWithSelectAll = () => { const [value, setValue] = createSignal([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = createMemo(() => value().length === items.length) const indeterminate = createMemo(() => value().length > 0 && value().length < items.length) return (
                    Selected: {JSON.stringify(value())} handleSelectAll(!!details.checked)} > JSX Frameworks {(item) => {item.label}}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet CheckboxItem(item: (typeof items)[number])} {item.label} {/snippet}
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {#each items as item (item.value)} {@render CheckboxItem(item)} {/each}
                    ``` ### Group Form Use the `Checkbox.Group` component within a form to handle multiple checkbox values with form submission. The `name` prop ensures all selected values are collected as an array when the form is submitted using `FormData.getAll()`. **Example: group-with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {items.map((item) => ( {item.label} ))}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {(item) => ( {item.label} )}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Fieldset Use the `Fieldset` component with `Checkbox.Group` to provide semantic grouping with legend, helper text, and error text support. **Example: group-with-fieldset** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Fieldset } from '@ark-ui/react/fieldset' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Fieldset } from '@ark-ui/solid/fieldset' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Select frameworks Choose your preferred frameworks {#each items as item (item.value)} {item.label} {/each} ``` ## Guides ### asChild Behavior The `Checkbox.Root` element of the checkbox is a `label` element. This is because the checkbox is a form control and should be associated with a label to provide context and meaning to the user. Otherwise, the HTML and accessibility structure will be invalid. > If you need to use the `asChild` property, make sure that the `label` element is the direct child of the > `Checkbox.Root` component. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[] | Accessor` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `Accessor` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `modelValue` | `string[]` | No | The controlled value of the checkbox group | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `{ isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean | undefined; readOnly: boolean | undefined; invalid: boolean | undefined; addValue: (val: string) => void; setValue: (value: string[]) => void; toggleValue: (val: string) => void; getItemProps: (itemProps:...` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CheckboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCheckboxReturn]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `ref` | `Element` | No | | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `() => { isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean; readOnly: boolean; invalid: boolean; setValue: (newValue: string[]) => void; addValue: (val: string) => void; toggleValue: (val: string) => void; getItemProps: (itemProps: CheckboxGroupItemProps) =>...` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `checked` | `boolean` | Whether the checkbox is checked | | `disabled` | `boolean` | Whether the checkbox is disabled | | `indeterminate` | `boolean` | Whether the checkbox is indeterminate | | `focused` | `boolean` | Whether the checkbox is focused | | `checkedState` | `CheckedState` | The checked state of the checkbox | | `setChecked` | `(checked: CheckedState) => void` | Function to set the checked state of the checkbox | | `toggleChecked` | `VoidFunction` | Function to toggle the checked state of the checkbox | ## Accessibility Complies with the [Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). ### Keyboard Support **`Space`** Description: Toggle the checkbox # Checkbox (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Basic = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Default Checked Use the `defaultChecked` prop to set the initial checked state in an uncontrolled manner. The checkbox will manage its own state internally. **Example: default-checked** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const DefaultChecked = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Controlled Use the `checked` and `onCheckedChange` props to programatically control the checkbox's state. **Example: controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = useState(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Controlled = () => { const [checked, setChecked] = createSignal(true) return ( setChecked(e.checked)}> Checkbox ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Root Provider An alternative way to control the checkbox is to use the `RootProvider` component and the `useCheckbox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Checkbox, useCheckbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox.checked ? ( ) : ( )}
                    ) } ``` #### Solid ```tsx import { Checkbox, useCheckbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const RootProvider = () => { const checkbox = useCheckbox() return (
                    Checkbox {checkbox().checked ? ( ) : ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Checkbox {#if checkbox().checked} {:else} {/if}
                    ``` ### Disabled Use the `disabled` prop to make the checkbox non-interactive. **Example: disabled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Disabled = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Indeterminate Use the `indeterminate` prop to create a checkbox in an indeterminate state (partially checked). **Example: indeterminate** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Indeterminate = () => ( Checkbox ) ``` #### Vue ```vue ``` #### Svelte ```svelte Checkbox ``` ### Field The checkbox integrates smoothly with the `Field` component to handle form state, helper text, and error text for proper accessibility. **Example: with-field** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Field } from '@ark-ui/react/field' import { CheckIcon, MinusIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Field } from '@ark-ui/solid/field' import { CheckIcon, MinusIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import field from 'styles/field.module.css' export const WithField = () => ( Label Additional Info Error Info ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label Additional Info Error Info ``` ### Form Pass the `name` and `value` props to the `Checkbox.Root` component to make the checkbox part of a form. The checkbox's value will be submitted with the form when the user submits it. **Example: with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const WithForm = () => (
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() const formData = new FormData(e.currentTarget) console.log('terms:', formData.get('terms')) }} > I agree to the terms and conditions
                    ``` ### Context Access the checkbox's state and methods with `Checkbox.Context` or the `useCheckboxContext` hook. **Example: context** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox.checked)}} ) ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import styles from 'styles/checkbox.module.css' export const Context = () => ( {(checkbox) => Checked: {String(checkbox().checked)}} ) ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(api)} Checked: {String(api().checked)} {/snippet} ``` ### Group Use the `Checkbox.Group` component to manage a group of checkboxes. The `Checkbox.Group` component manages the state of the checkboxes and provides a way to access the checked values. **Example: group** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const Group = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const Group = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Controlled Group Use the `value` and `onValueChange` props to programmatically control the checkbox group's state. This example demonstrates how to manage selected checkboxes in an array and display the current selection. **Example: group-controlled** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = useState(['react']) return (
                    value: {JSON.stringify(value)} {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { createSignal, For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupControlled = () => { const [value, setValue] = createSignal(['react']) return (
                    value: {JSON.stringify(value())} {(item) => ( {item.label} )}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {JSON.stringify(value)} {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Group Provider Use the `useCheckboxGroup` hook to create the checkbox group store and pass it to the `Checkbox.GroupProvider` component. This provides maximum control over the group programmatically, similar to how `RootProvider` works for individual checkboxes. **Example: group-provider** #### React ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {items.map((item) => ( {item.label} ))} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox, useCheckboxGroup } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupProvider = () => { const group = useCheckboxGroup({ defaultValue: ['react'], name: 'framework', }) return ( {(item) => ( {item.label} )} ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Invalid Use the `invalid` prop on `Checkbox.Group` to mark the entire group as invalid for validation purposes. This applies the invalid state to all checkboxes within the group. **Example: group-with-invalid** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' export const GroupWithInvalid = () => ( {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#each items as item (item.value)} {item.label} {/each} ``` ### Select All Implement a "select all" checkbox that controls all checkboxes within a group. The parent checkbox automatically shows an indeterminate state when some (but not all) items are selected, and becomes fully checked when all items are selected. **Example: group-with-select-all** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon, MinusIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => { return ( {props.children} ) } export const GroupWithSelectAll = () => { const [value, setValue] = useState([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = value.length === items.length const indeterminate = value.length > 0 && value.length < items.length return (
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {items.map((item) => ( {item.label} ))}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon, MinusIcon } from 'lucide-solid' import { For, createSignal, createMemo } from 'solid-js' import styles from 'styles/checkbox.module.css' const CheckboxItem = (props: Checkbox.RootProps) => ( {props.children} ) export const GroupWithSelectAll = () => { const [value, setValue] = createSignal([]) const handleSelectAll = (checked: boolean) => { setValue(checked ? items.map((item) => item.value) : []) } const allSelected = createMemo(() => value().length === items.length) const indeterminate = createMemo(() => value().length > 0 && value().length < items.length) return (
                    Selected: {JSON.stringify(value())} handleSelectAll(!!details.checked)} > JSX Frameworks {(item) => {item.label}}
                    ) } const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet CheckboxItem(item: (typeof items)[number])} {item.label} {/snippet}
                    Selected: {JSON.stringify(value)} handleSelectAll(!!e.checked)} > JSX Frameworks {#each items as item (item.value)} {@render CheckboxItem(item)} {/each}
                    ``` ### Group Form Use the `Checkbox.Group` component within a form to handle multiple checkbox values with form submission. The `name` prop ensures all selected values are collected as an array when the form is submitted using `FormData.getAll()`. **Example: group-with-form** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {items.map((item) => ( {item.label} ))}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import button from 'styles/button.module.css' export const GroupWithForm = () => (
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {(item) => ( {item.label} )}
                    ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() console.log(new FormData(e.currentTarget).getAll('framework')) }} > {#each items as item (item.value)} {item.label} {/each}
                    ``` ### Fieldset Use the `Fieldset` component with `Checkbox.Group` to provide semantic grouping with legend, helper text, and error text support. **Example: group-with-fieldset** #### React ```tsx import { Checkbox } from '@ark-ui/react/checkbox' import { Fieldset } from '@ark-ui/react/fieldset' import { CheckIcon } from 'lucide-react' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {items.map((item) => ( {item.label} ))} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Solid ```tsx import { Checkbox } from '@ark-ui/solid/checkbox' import { Fieldset } from '@ark-ui/solid/fieldset' import { CheckIcon } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/checkbox.module.css' import fieldset from 'styles/fieldset.module.css' export const GroupWithFieldset = () => ( Select frameworks Choose your preferred frameworks {(item) => ( {item.label} )} ) const items = [ { label: 'React', value: 'react' }, { label: 'Solid', value: 'solid' }, { label: 'Vue', value: 'vue' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Select frameworks Choose your preferred frameworks {#each items as item (item.value)} {item.label} {/each} ``` ## Guides ### asChild Behavior The `Checkbox.Root` element of the checkbox is a `label` element. This is because the checkbox is a form control and should be associated with a label to provide context and meaning to the user. Otherwise, the HTML and accessibility structure will be invalid. > If you need to use the `asChild` property, make sure that the `label` element is the direct child of the > `Checkbox.Root` component. ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[] | Accessor` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `value` | `Accessor` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxGroupContext` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `modelValue` | `string[]` | No | The controlled value of the checkbox group | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `{ isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean | undefined; readOnly: boolean | undefined; invalid: boolean | undefined; addValue: (val: string) => void; setValue: (value: string[]) => void; toggleValue: (val: string) => void; getItemProps: (itemProps:...` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `CheckboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `checked` | `CheckedState` | No | The controlled checked state of the checkbox | | `defaultChecked` | `CheckedState` | No | The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. | | `disabled` | `boolean` | No | Whether the checkbox is disabled | | `form` | `string` | No | The id of the form that the checkbox belongs to. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; hiddenInput: string; control: string; label: string }>` | No | The ids of the elements in the checkbox. Useful for composition. | | `invalid` | `boolean` | No | Whether the checkbox is invalid | | `name` | `string` | No | The name of the input field in a checkbox. Useful for form submission. | | `onCheckedChange` | `(details: CheckedChangeDetails) => void` | No | The callback invoked when the checked state changes. | | `readOnly` | `boolean` | No | Whether the checkbox is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the checkbox is required | | `value` | `string` | No | The value of checkbox input. Useful for form submission. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCheckboxReturn]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Group Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string[]` | No | The initial value of `value` when uncontrolled | | `disabled` | `boolean` | No | If `true`, the checkbox group is disabled | | `invalid` | `boolean` | No | If `true`, the checkbox group is invalid | | `name` | `string` | No | The name of the input fields in the checkbox group (Useful for form submission). | | `onValueChange` | `(value: string[]) => void` | No | The callback to call when the value changes | | `readOnly` | `boolean` | No | If `true`, the checkbox group is read-only | | `ref` | `Element` | No | | | `value` | `string[]` | No | The controlled value of the checkbox group | **GroupProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `() => { isChecked: (val: string | undefined) => boolean; value: string[]; name: string | undefined; disabled: boolean; readOnly: boolean; invalid: boolean; setValue: (newValue: string[]) => void; addValue: (val: string) => void; toggleValue: (val: string) => void; getItemProps: (itemProps: CheckboxGroupItemProps) =>...` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `indeterminate` | `boolean` | No | | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-active]` | Present when active or pressed | | `[data-focus]` | Present when focused | | `[data-focus-visible]` | Present when focused with keyboard | | `[data-readonly]` | Present when read-only | | `[data-hover]` | Present when hovered | | `[data-disabled]` | Present when disabled | | `[data-state]` | "indeterminate" | "checked" | "unchecked" | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCheckboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `checked` | `boolean` | Whether the checkbox is checked | | `disabled` | `boolean` | Whether the checkbox is disabled | | `indeterminate` | `boolean` | Whether the checkbox is indeterminate | | `focused` | `boolean` | Whether the checkbox is focused | | `checkedState` | `CheckedState` | The checked state of the checkbox | | `setChecked` | `(checked: CheckedState) => void` | Function to set the checked state of the checkbox | | `toggleChecked` | `VoidFunction` | Function to toggle the checked state of the checkbox | ## Accessibility Complies with the [Checkbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). ### Keyboard Support **`Space`** Description: Toggle the checkbox # Clipboard (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet copied()} {/snippet} ``` ### Controlled Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates. **Example: controlled** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = useState('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = createSignal('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Copy this link {#snippet copied()} {/snippet}
                    ``` ### Root Provider An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Clipboard, useClipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard.value}, copied: {String(clipboard.copied)} Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard, useClipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link {#snippet copied()} {/snippet}
                    ``` ### Context Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like `copied`, `value`, and `setValue`. > Alternatively, you can use the `useClipboardContext` hook to access the clipboard context. **Example: context** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { Show } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet render(clipboard)} {/snippet} ``` ### Copy Status Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display a success message. **Example: copy-status** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = useState(0) return ( { if (details.copied) setCopyCount((prev) => prev + 1) }} > }>

                    Copied {copyCount} times

                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = createSignal(0) return ( { if (details.copied) { setCopyCount((prev) => prev + 1) } }} > }>

                    Copied {copyCount()} times

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte { if (details.copied) { copyCount += 1 } }} > {#snippet copied()} {/snippet}

                    Copied {copyCount} times

                    ``` ### Timeout Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds). **Example: timeout** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link (5 second timeout) {#snippet copied()} {/snippet} ``` ### Value Text Use `Clipboard.ValueText` to display the current clipboard value. **Example: value-text** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet copied()} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `number | boolean | Node | ArrayElement | (string & {})` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `modelValue` | `string` | No | The v-model value of the clipboard | | `timeout` | `number` | No | The timeout for the copy operation | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ClipboardApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `ref` | `Element` | No | | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseClipboardContext]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `Snippet<[]>` | No | | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `copied` | `boolean` | Whether the value has been copied to the clipboard | | `value` | `string` | The value to be copied to the clipboard | | `setValue` | `(value: string) => void` | Set the value to be copied to the clipboard | | `copy` | `VoidFunction` | Copy the value to the clipboard | # Clipboard (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet copied()} {/snippet} ``` ### Controlled Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates. **Example: controlled** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = useState('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = createSignal('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Copy this link {#snippet copied()} {/snippet}
                    ``` ### Root Provider An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Clipboard, useClipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard.value}, copied: {String(clipboard.copied)} Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard, useClipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link {#snippet copied()} {/snippet}
                    ``` ### Context Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like `copied`, `value`, and `setValue`. > Alternatively, you can use the `useClipboardContext` hook to access the clipboard context. **Example: context** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { Show } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet render(clipboard)} {/snippet} ``` ### Copy Status Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display a success message. **Example: copy-status** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = useState(0) return ( { if (details.copied) setCopyCount((prev) => prev + 1) }} > }>

                    Copied {copyCount} times

                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = createSignal(0) return ( { if (details.copied) { setCopyCount((prev) => prev + 1) } }} > }>

                    Copied {copyCount()} times

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte { if (details.copied) { copyCount += 1 } }} > {#snippet copied()} {/snippet}

                    Copied {copyCount} times

                    ``` ### Timeout Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds). **Example: timeout** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link (5 second timeout) {#snippet copied()} {/snippet} ``` ### Value Text Use `Clipboard.ValueText` to display the current clipboard value. **Example: value-text** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet copied()} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `number | boolean | Node | ArrayElement | (string & {})` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `modelValue` | `string` | No | The v-model value of the clipboard | | `timeout` | `number` | No | The timeout for the copy operation | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ClipboardApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `ref` | `Element` | No | | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseClipboardContext]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `Snippet<[]>` | No | | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `copied` | `boolean` | Whether the value has been copied to the clipboard | | `value` | `string` | The value to be copied to the clipboard | | `setValue` | `(value: string) => void` | Set the value to be copied to the clipboard | | `copy` | `VoidFunction` | Copy the value to the clipboard | # Clipboard (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet copied()} {/snippet} ``` ### Controlled Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates. **Example: controlled** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = useState('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = createSignal('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Copy this link {#snippet copied()} {/snippet}
                    ``` ### Root Provider An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Clipboard, useClipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard.value}, copied: {String(clipboard.copied)} Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard, useClipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link {#snippet copied()} {/snippet}
                    ``` ### Context Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like `copied`, `value`, and `setValue`. > Alternatively, you can use the `useClipboardContext` hook to access the clipboard context. **Example: context** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { Show } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet render(clipboard)} {/snippet} ``` ### Copy Status Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display a success message. **Example: copy-status** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = useState(0) return ( { if (details.copied) setCopyCount((prev) => prev + 1) }} > }>

                    Copied {copyCount} times

                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = createSignal(0) return ( { if (details.copied) { setCopyCount((prev) => prev + 1) } }} > }>

                    Copied {copyCount()} times

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte { if (details.copied) { copyCount += 1 } }} > {#snippet copied()} {/snippet}

                    Copied {copyCount} times

                    ``` ### Timeout Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds). **Example: timeout** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link (5 second timeout) {#snippet copied()} {/snippet} ``` ### Value Text Use `Clipboard.ValueText` to display the current clipboard value. **Example: value-text** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet copied()} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `number | boolean | Node | ArrayElement | (string & {})` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `modelValue` | `string` | No | The v-model value of the clipboard | | `timeout` | `number` | No | The timeout for the copy operation | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ClipboardApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `ref` | `Element` | No | | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseClipboardContext]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `Snippet<[]>` | No | | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `copied` | `boolean` | Whether the value has been copied to the clipboard | | `value` | `string` | The value to be copied to the clipboard | | `setValue` | `(value: string) => void` | Set the value to be copied to the clipboard | | `copy` | `VoidFunction` | Copy the value to the clipboard | # Clipboard (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Basic = () => { return ( Copy this link }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet copied()} {/snippet} ``` ### Controlled Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates. **Example: controlled** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = useState('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Controlled = () => { const [url, setUrl] = createSignal('https://ark-ui.com') return (
                    setUrl(details.value)}> Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Copy this link {#snippet copied()} {/snippet}
                    ``` ### Root Provider An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Clipboard, useClipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard.value}, copied: {String(clipboard.copied)} Copy this link }>
                    ) } ``` #### Solid ```tsx import { Clipboard, useClipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const RootProvider = () => { const clipboard = useClipboard({ value: 'https://ark-ui.com' }) return (
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link }>
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    value: {clipboard().value}, copied: {String(clipboard().copied)} Copy this link {#snippet copied()} {/snippet}
                    ``` ### Context Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like `copied`, `value`, and `setValue`. > Alternatively, you can use the `useClipboardContext` hook to access the clipboard context. **Example: context** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { Show } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/clipboard.module.css' export const Context = () => { return ( Copy this link {(clipboard) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link {#snippet render(clipboard)} {/snippet} ``` ### Copy Status Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display a success message. **Example: copy-status** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = useState(0) return ( { if (details.copied) setCopyCount((prev) => prev + 1) }} > }>

                    Copied {copyCount} times

                    ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/clipboard.module.css' export const CopyStatus = () => { const [copyCount, setCopyCount] = createSignal(0) return ( { if (details.copied) { setCopyCount((prev) => prev + 1) } }} > }>

                    Copied {copyCount()} times

                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte { if (details.copied) { copyCount += 1 } }} > {#snippet copied()} {/snippet}

                    Copied {copyCount} times

                    ``` ### Timeout Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds). **Example: timeout** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const Timeout = () => { return ( Copy this link (5 second timeout) }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Copy this link (5 second timeout) {#snippet copied()} {/snippet} ``` ### Value Text Use `Clipboard.ValueText` to display the current clipboard value. **Example: value-text** #### React ```tsx import { Clipboard } from '@ark-ui/react/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-react' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Solid ```tsx import { Clipboard } from '@ark-ui/solid/clipboard' import { CheckIcon, ClipboardCopyIcon } from 'lucide-solid' import styles from 'styles/clipboard.module.css' export const ValueText = () => { return ( }> ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet copied()} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `string | number | bigint | boolean | ReactElement> | Iterable | ReactPortal | Promise<...>` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `number | boolean | Node | ArrayElement | (string & {})` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `modelValue` | `string` | No | The v-model value of the clipboard | | `timeout` | `number` | No | The timeout for the copy operation | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ClipboardApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. | | `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes | | `ref` | `Element` | No | | | `timeout` | `number` | No | The timeout for the copy operation | | `value` | `string` | No | The controlled value of the clipboard | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | root | | `[data-copied]` | Present when copied state is true | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseClipboardContext]>` | No | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | control | | `[data-copied]` | Present when copied state is true | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `copied` | `Snippet<[]>` | No | | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | input | | `[data-copied]` | Present when copied state is true | | `[data-readonly]` | Present when read-only | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | label | | `[data-copied]` | Present when copied state is true | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseClipboardReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | clipboard | | `[data-part]` | trigger | | `[data-copied]` | Present when copied state is true | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `copied` | `boolean` | Whether the value has been copied to the clipboard | | `value` | `string` | The value to be copied to the clipboard | | `setValue` | `(value: string) => void` | Set the value to be copied to the clipboard | | `copy` | `VoidFunction` | Copy the value to the clipboard | # Collapsible (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ``` ### Disabled Use the `disabled` prop to disable the collapsible and prevent it from being toggled. **Example: disabled** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte System Requirements
                    This section is currently unavailable.
                    ``` ### Partial Collapse Use the `collapsedHeight` or `collapsedWidth` props to create a "show more/less" pattern. When set, the content maintains the specified dimensions when collapsed instead of collapsing to 0px. We expose the `--collapsed-height` or `--collapsed-width` variables to use in your CSS animations. **Example: partial-collapse** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ``` > Interactive elements (links, buttons, inputs) within the collapsed area automatically become `inert` to prevent > keyboard navigation to hidden content. ### Nested Collapsibles You can nest collapsibles within collapsibles to create hierarchical content structures. **Example: nested** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/react
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/solid
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/svelte
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ``` ### Lazy Mount Use `lazyMount` to delay mounting the content until first opened, and `unmountOnExit` to remove it from the DOM when collapsed. Combining both ensures the component is only in the DOM while expanded. **Example: lazy-mount** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ``` ### Root Provider An alternative way to control the collapsible is to use the `RootProvider` component and the `useCollapsible` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Collapsible, useCollapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    collapsible: {String(collapsible.open)}, visible: {String(collapsible.visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Solid ```tsx import { Collapsible, useCollapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ``` ## Guides ### Indicator Animation To rotate the indicator icon (such as a chevron) when the collapsible opens and closes, use CSS transforms with the `data-state` attribute: ```css [data-scope='collapsible'][data-part='indicator'] { transition: transform 200ms; &[data-state='open'] { transform: rotate(180deg); } } ``` ### Open vs Visible When using `useCollapsible` or `useCollapsibleContext`, you can access the `open` and `visible` state properties. They seem similar but serve different purposes: - **`open`**: Indicates the intended state of the collapsible. This is `true` when the collapsible should be expanded and `false` when it should be collapsed. This changes immediately when triggered. - **`visible`**: Indicates whether the content is currently visible in the DOM. This accounts for exit animations - the content remains `visible` while the closing animation plays, even though `open` is already `false`. Once the animation completes, `visible` becomes `false`. ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes. If you use `collapsedHeight` or `collapsedWidth`, update your CSS animations to use the `--collapsed-height` or `--collapsed-width` variables as the starting/ending point: ```css @keyframes expand { from { height: var(--collapsed-height, 0); } to { height: var(--height); } } @keyframes collapse { from { height: var(--height); } to { height: var(--collapsed-height, 0); } } [data-scope='collapsible'][data-part='content'] { &[data-state='open'] { animation: expand 250ms; } &[data-state='closed'] { animation: collapse 250ms; } } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Collapsible` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether the content should be lazy mounted | | `onExitComplete` | `() => void` | No | Callback fired when the animation ends | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether the content should be unmounted when collapsed | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCollapsibleContext]>` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `open` | `boolean` | Whether the collapsible is open. | | `visible` | `boolean` | Whether the collapsible is visible (open or closing) | | `disabled` | `boolean` | Whether the collapsible is disabled | | `setOpen` | `(open: boolean) => void` | Function to open or close the collapsible. | | `measureSize` | `VoidFunction` | Function to measure the size of the content. | ## Accessibility ### Keyboard Support **`Space`** Description: Opens/closes the collapsible. **`Enter`** Description: Opens/closes the collapsible. # Collapsible (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ``` ### Disabled Use the `disabled` prop to disable the collapsible and prevent it from being toggled. **Example: disabled** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte System Requirements
                    This section is currently unavailable.
                    ``` ### Partial Collapse Use the `collapsedHeight` or `collapsedWidth` props to create a "show more/less" pattern. When set, the content maintains the specified dimensions when collapsed instead of collapsing to 0px. We expose the `--collapsed-height` or `--collapsed-width` variables to use in your CSS animations. **Example: partial-collapse** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ``` > Interactive elements (links, buttons, inputs) within the collapsed area automatically become `inert` to prevent > keyboard navigation to hidden content. ### Nested Collapsibles You can nest collapsibles within collapsibles to create hierarchical content structures. **Example: nested** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/react
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/solid
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/svelte
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ``` ### Lazy Mount Use `lazyMount` to delay mounting the content until first opened, and `unmountOnExit` to remove it from the DOM when collapsed. Combining both ensures the component is only in the DOM while expanded. **Example: lazy-mount** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ``` ### Root Provider An alternative way to control the collapsible is to use the `RootProvider` component and the `useCollapsible` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Collapsible, useCollapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    collapsible: {String(collapsible.open)}, visible: {String(collapsible.visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Solid ```tsx import { Collapsible, useCollapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ``` ## Guides ### Indicator Animation To rotate the indicator icon (such as a chevron) when the collapsible opens and closes, use CSS transforms with the `data-state` attribute: ```css [data-scope='collapsible'][data-part='indicator'] { transition: transform 200ms; &[data-state='open'] { transform: rotate(180deg); } } ``` ### Open vs Visible When using `useCollapsible` or `useCollapsibleContext`, you can access the `open` and `visible` state properties. They seem similar but serve different purposes: - **`open`**: Indicates the intended state of the collapsible. This is `true` when the collapsible should be expanded and `false` when it should be collapsed. This changes immediately when triggered. - **`visible`**: Indicates whether the content is currently visible in the DOM. This accounts for exit animations - the content remains `visible` while the closing animation plays, even though `open` is already `false`. Once the animation completes, `visible` becomes `false`. ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes. If you use `collapsedHeight` or `collapsedWidth`, update your CSS animations to use the `--collapsed-height` or `--collapsed-width` variables as the starting/ending point: ```css @keyframes expand { from { height: var(--collapsed-height, 0); } to { height: var(--height); } } @keyframes collapse { from { height: var(--height); } to { height: var(--collapsed-height, 0); } } [data-scope='collapsible'][data-part='content'] { &[data-state='open'] { animation: expand 250ms; } &[data-state='closed'] { animation: collapse 250ms; } } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Collapsible` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether the content should be lazy mounted | | `onExitComplete` | `() => void` | No | Callback fired when the animation ends | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether the content should be unmounted when collapsed | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCollapsibleContext]>` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `open` | `boolean` | Whether the collapsible is open. | | `visible` | `boolean` | Whether the collapsible is visible (open or closing) | | `disabled` | `boolean` | Whether the collapsible is disabled | | `setOpen` | `(open: boolean) => void` | Function to open or close the collapsible. | | `measureSize` | `VoidFunction` | Function to measure the size of the content. | ## Accessibility ### Keyboard Support **`Space`** Description: Opens/closes the collapsible. **`Enter`** Description: Opens/closes the collapsible. # Collapsible (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ``` ### Disabled Use the `disabled` prop to disable the collapsible and prevent it from being toggled. **Example: disabled** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte System Requirements
                    This section is currently unavailable.
                    ``` ### Partial Collapse Use the `collapsedHeight` or `collapsedWidth` props to create a "show more/less" pattern. When set, the content maintains the specified dimensions when collapsed instead of collapsing to 0px. We expose the `--collapsed-height` or `--collapsed-width` variables to use in your CSS animations. **Example: partial-collapse** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ``` > Interactive elements (links, buttons, inputs) within the collapsed area automatically become `inert` to prevent > keyboard navigation to hidden content. ### Nested Collapsibles You can nest collapsibles within collapsibles to create hierarchical content structures. **Example: nested** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/react
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/solid
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/svelte
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ``` ### Lazy Mount Use `lazyMount` to delay mounting the content until first opened, and `unmountOnExit` to remove it from the DOM when collapsed. Combining both ensures the component is only in the DOM while expanded. **Example: lazy-mount** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ``` ### Root Provider An alternative way to control the collapsible is to use the `RootProvider` component and the `useCollapsible` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Collapsible, useCollapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    collapsible: {String(collapsible.open)}, visible: {String(collapsible.visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Solid ```tsx import { Collapsible, useCollapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ``` ## Guides ### Indicator Animation To rotate the indicator icon (such as a chevron) when the collapsible opens and closes, use CSS transforms with the `data-state` attribute: ```css [data-scope='collapsible'][data-part='indicator'] { transition: transform 200ms; &[data-state='open'] { transform: rotate(180deg); } } ``` ### Open vs Visible When using `useCollapsible` or `useCollapsibleContext`, you can access the `open` and `visible` state properties. They seem similar but serve different purposes: - **`open`**: Indicates the intended state of the collapsible. This is `true` when the collapsible should be expanded and `false` when it should be collapsed. This changes immediately when triggered. - **`visible`**: Indicates whether the content is currently visible in the DOM. This accounts for exit animations - the content remains `visible` while the closing animation plays, even though `open` is already `false`. Once the animation completes, `visible` becomes `false`. ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes. If you use `collapsedHeight` or `collapsedWidth`, update your CSS animations to use the `--collapsed-height` or `--collapsed-width` variables as the starting/ending point: ```css @keyframes expand { from { height: var(--collapsed-height, 0); } to { height: var(--height); } } @keyframes collapse { from { height: var(--height); } to { height: var(--collapsed-height, 0); } } [data-scope='collapsible'][data-part='content'] { &[data-state='open'] { animation: expand 250ms; } &[data-state='closed'] { animation: collapse 250ms; } } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Collapsible` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether the content should be lazy mounted | | `onExitComplete` | `() => void` | No | Callback fired when the animation ends | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether the content should be unmounted when collapsed | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCollapsibleContext]>` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `open` | `boolean` | Whether the collapsible is open. | | `visible` | `boolean` | Whether the collapsible is visible (open or closing) | | `disabled` | `boolean` | Whether the collapsible is disabled | | `setOpen` | `(open: boolean) => void` | Function to open or close the collapsible. | | `measureSize` | `VoidFunction` | Function to measure the size of the content. | ## Accessibility ### Keyboard Support **`Space`** Description: Opens/closes the collapsible. **`Enter`** Description: Opens/closes the collapsible. # Collapsible (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Basic = () => ( What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte What is Ark UI?
                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte.
                    ``` ### Disabled Use the `disabled` prop to disable the collapsible and prevent it from being toggled. **Example: disabled** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Disabled = () => ( System Requirements
                    This section is currently unavailable.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte System Requirements
                    This section is currently unavailable.
                    ``` ### Partial Collapse Use the `collapsedHeight` or `collapsedWidth` props to create a "show more/less" pattern. When set, the content maintains the specified dimensions when collapsed instead of collapsing to 0px. We expose the `--collapsed-height` or `--collapsed-width` variables to use in your CSS animations. **Example: partial-collapse** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const PartialCollapse = () => ( Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Read More

                    Ark UI is a headless component library for building accessible, high-quality UI components for React, Solid, Vue, and Svelte. It provides unstyled, fully accessible components that you can customize to match your design system.

                    Built on top of Zag.js state machines, Ark UI ensures consistent behavior across all frameworks while giving you complete control over styling. Each component follows WAI-ARIA patterns for accessibility out of the box.

                    Whether you're building a design system from scratch or need reliable primitives for your next project, Ark UI provides the foundation you need without imposing any visual constraints.

                    ``` > Interactive elements (links, buttons, inputs) within the collapsed area automatically become `inert` to prevent > keyboard navigation to hidden content. ### Nested Collapsibles You can nest collapsibles within collapsibles to create hierarchical content structures. **Example: nested** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/react
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const Nested = () => ( Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/solid
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Getting Started

                    Welcome to the Ark UI documentation. Here are some topics to explore:

                    Installation

                    Install Ark UI using your preferred package manager:

                    npm install @ark-ui/svelte
                    Styling

                    Ark UI components are unstyled by default. Use CSS modules, Tailwind, or any styling solution.

                    ``` ### Lazy Mount Use `lazyMount` to delay mounting the content until first opened, and `unmountOnExit` to remove it from the DOM when collapsed. Combining both ensures the component is only in the DOM while expanded. **Example: lazy-mount** #### React ```tsx import { Collapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Solid ```tsx import { Collapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const LazyMount = () => ( Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Session Details
                    This content is lazily mounted when first opened and removed from the DOM when collapsed.
                    ``` ### Root Provider An alternative way to control the collapsible is to use the `RootProvider` component and the `useCollapsible` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Collapsible, useCollapsible } from '@ark-ui/react/collapsible' import { ChevronRightIcon } from 'lucide-react' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    collapsible: {String(collapsible.open)}, visible: {String(collapsible.visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Solid ```tsx import { Collapsible, useCollapsible } from '@ark-ui/solid/collapsible' import { ChevronRightIcon } from 'lucide-solid' import styles from 'styles/collapsible.module.css' export const RootProvider = () => { const collapsible = useCollapsible() return (
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    open: {String(collapsible().open)}, visible: {String(collapsible().visible)} Toggle Panel
                    This panel can be toggled by the button above, which uses the useCollapsible hook for state management.
                    ``` ## Guides ### Indicator Animation To rotate the indicator icon (such as a chevron) when the collapsible opens and closes, use CSS transforms with the `data-state` attribute: ```css [data-scope='collapsible'][data-part='indicator'] { transition: transform 200ms; &[data-state='open'] { transform: rotate(180deg); } } ``` ### Open vs Visible When using `useCollapsible` or `useCollapsibleContext`, you can access the `open` and `visible` state properties. They seem similar but serve different purposes: - **`open`**: Indicates the intended state of the collapsible. This is `true` when the collapsible should be expanded and `false` when it should be collapsed. This changes immediately when triggered. - **`visible`**: Indicates whether the content is currently visible in the DOM. This accounts for exit animations - the content remains `visible` while the closing animation plays, even though `open` is already `false`. Once the animation completes, `visible` becomes `false`. ### Content Animation Use the `--height` and/or `--width` CSS variables to animate the size of the content when it expands or closes. If you use `collapsedHeight` or `collapsedWidth`, update your CSS animations to use the `--collapsed-height` or `--collapsed-width` variables as the starting/ending point: ```css @keyframes expand { from { height: var(--collapsed-height, 0); } to { height: var(--height); } } @keyframes collapse { from { height: var(--height); } to { height: var(--collapsed-height, 0); } } [data-scope='collapsible'][data-part='content'] { &[data-state='open'] { animation: expand 250ms; } &[data-state='closed'] { animation: collapse 250ms; } } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | The callback invoked when the exit animation completes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Collapsible` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `collapsedHeight` | `string | number` | No | The height of the content when collapsed. | | `collapsedWidth` | `string | number` | No | The width of the content when collapsed. | | `defaultOpen` | `boolean` | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. | | `disabled` | `boolean` | No | Whether the collapsible is disabled. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; content: string; trigger: string }>` | No | The ids of the elements in the collapsible. Useful for composition. | | `lazyMount` | `boolean` | No | Whether the content should be lazy mounted | | `onExitComplete` | `() => void` | No | Callback fired when the animation ends | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | The callback invoked when the open state changes. | | `open` | `boolean` | No | The controlled open state of the collapsible. | | `ref` | `Element` | No | | | `unmountOnExit` | `boolean` | No | Whether the content should be unmounted when collapsed | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | content | | `[data-collapsible]` | | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-has-collapsed-size]` | Present when the content has collapsed width or height | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--height` | The height of the element | | `--width` | The width of the element | | `--collapsed-height` | The height of the Content | | `--collapsed-width` | The width of the Content | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseCollapsibleContext]>` | No | | **Indicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Indicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | indicator | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseCollapsibleReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | collapsible | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `open` | `boolean` | Whether the collapsible is open. | | `visible` | `boolean` | Whether the collapsible is visible (open or closing) | | `disabled` | `boolean` | Whether the collapsible is disabled | | `setOpen` | `(open: boolean) => void` | Function to open or close the collapsible. | | `measureSize` | `VoidFunction` | Function to measure the size of the content. | ## Accessibility ### Keyboard Support **`Space`** Description: Opens/closes the collapsible. **`Enter`** Description: Opens/closes the collapsible. # Color Picker (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Controlled Use the `value` and `onValueChange` props to programatically control the color picker's state. **Example: controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = useState(() => parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color.toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = createSignal(parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color().toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected color: {value.toString('hex')} Color
                    ``` ### Open Controlled Control the open state of the color picker popover programmatically using the `open` and `onOpenChange` props. **Example: open-controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = useState(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = createSignal(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color
                    ``` ### Root Provider An alternative way to control the color picker is to use the `RootProvider` component and the `useColorPicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker.valueAsString} Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker().valueAsString} Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color: {colorPicker().valueAsString} Color
                    {#each swatches as color} {/each}
                    ``` ### Disabled Use the `disabled` prop to disable the color picker. **Example: disabled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Inline Render the color picker inline without a popover by using the `inline` prop. **Example: inline** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each swatches as color} {/each} ``` ### Input Only A minimal color picker with just an input field, value swatch, and eye dropper trigger. **Example: input-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color ``` ### Slider Only Display only the channel sliders for RGB color selection. **Example: slider-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    R
                    G
                    B
                    ``` ### Swatch Only A simple color picker with only preset color swatches. **Example: swatch-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Selected color: {#each swatches as color} {/each} ``` ### Swatches Include preset color swatches in the color picker content for quick color selection. **Example: swatches** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    {#each swatches as color} {/each}
                    ``` ### Value Swatch Display the current color value as a swatch alongside the color area and sliders. **Example: value-swatch** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a color picker. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { Field } from '@ark-ui/react/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Field } from '@ark-ui/solid/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Additional Info Error Info
                    ``` ### Form Usage Integrate the color picker with form libraries like React Hook Form using the `HiddenInput` component. **Example: form-usage** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useForm } from 'react-hook-form' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' interface FieldValues { color: string } export const FormUsage = () => { const { register, handleSubmit } = useForm() const onSubmit = (data: FieldValues) => { alert(data) } return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { createForm, setValue } from '@modular-forms/solid' import { Pipette } from 'lucide-solid' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const FormUsage = () => { const [formStore, { Form, Field }] = createForm<{ color: string }>() return (
                    { window.alert(JSON.stringify(data)) }} > {(field) => ( setValue(formStore, 'color', details.valueAsString)} >
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() form.handleSubmit() }} > {#snippet children(field)} field.handleChange(details.valueAsString)} >
                    {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput(id: string): string; channelSliderTrack(id: ColorChannel): string; channelSliderT...` | No | The ids of the elements in the color picker. Useful for composition. | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether the color picker is inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `Color` | No | The v-model value of the color picker | | `name` | `string` | No | The name for the form input | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ColorPickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseColorPickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | | `ref` | `Element` | No | | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | | `ref` | `Element` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `dragging` | `boolean` | Whether the color picker is being dragged | | `open` | `boolean` | Whether the color picker is open | | `inline` | `boolean` | Whether the color picker is rendered inline | | `value` | `Color` | The current color value (as a string) | | `valueAsString` | `string` | The current color value (as a Color object) | | `setValue` | `(value: string | Color) => void` | Function to set the color value | | `getChannelValue` | `(channel: ColorChannel) => string` | Function to set the color value | | `getChannelValueText` | `(channel: ColorChannel, locale: string) => string` | Function to get the formatted and localized value of a specific channel | | `setChannelValue` | `(channel: ColorChannel, value: number) => void` | Function to set the color value of a specific channel | | `format` | `ColorFormat` | The current color format | | `setFormat` | `(format: ColorFormat) => void` | Function to set the color format | | `alpha` | `number` | The alpha value of the color | | `setAlpha` | `(value: number) => void` | Function to set the color alpha | | `setOpen` | `(open: boolean) => void` | Function to open or close the color picker | ## Accessibility ### Keyboard Support **`Enter`** Description: When focus is on the trigger, opens the color picker
                    When focus is on a trigger of a swatch, selects the color (and closes the color picker)
                    When focus is on the input or channel inputs, selects the color
                    **`ArrowLeft`** Description: When focus is on the color area, decreases the hue value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`ArrowRight`** Description: When focus is on the color area, increases the hue value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowUp`** Description: When focus is on the color area, increases the saturation value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowDown`** Description: When focus is on the color area, decreases the saturation value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`Esc`** Description: Closes the color picker and moves focus to the trigger # Color Picker (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Controlled Use the `value` and `onValueChange` props to programatically control the color picker's state. **Example: controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = useState(() => parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color.toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = createSignal(parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color().toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected color: {value.toString('hex')} Color
                    ``` ### Open Controlled Control the open state of the color picker popover programmatically using the `open` and `onOpenChange` props. **Example: open-controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = useState(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = createSignal(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color
                    ``` ### Root Provider An alternative way to control the color picker is to use the `RootProvider` component and the `useColorPicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker.valueAsString} Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker().valueAsString} Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color: {colorPicker().valueAsString} Color
                    {#each swatches as color} {/each}
                    ``` ### Disabled Use the `disabled` prop to disable the color picker. **Example: disabled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Inline Render the color picker inline without a popover by using the `inline` prop. **Example: inline** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each swatches as color} {/each} ``` ### Input Only A minimal color picker with just an input field, value swatch, and eye dropper trigger. **Example: input-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color ``` ### Slider Only Display only the channel sliders for RGB color selection. **Example: slider-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    R
                    G
                    B
                    ``` ### Swatch Only A simple color picker with only preset color swatches. **Example: swatch-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Selected color: {#each swatches as color} {/each} ``` ### Swatches Include preset color swatches in the color picker content for quick color selection. **Example: swatches** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    {#each swatches as color} {/each}
                    ``` ### Value Swatch Display the current color value as a swatch alongside the color area and sliders. **Example: value-swatch** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a color picker. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { Field } from '@ark-ui/react/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Field } from '@ark-ui/solid/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Additional Info Error Info
                    ``` ### Form Usage Integrate the color picker with form libraries like React Hook Form using the `HiddenInput` component. **Example: form-usage** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useForm } from 'react-hook-form' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' interface FieldValues { color: string } export const FormUsage = () => { const { register, handleSubmit } = useForm() const onSubmit = (data: FieldValues) => { alert(data) } return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { createForm, setValue } from '@modular-forms/solid' import { Pipette } from 'lucide-solid' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const FormUsage = () => { const [formStore, { Form, Field }] = createForm<{ color: string }>() return (
                    { window.alert(JSON.stringify(data)) }} > {(field) => ( setValue(formStore, 'color', details.valueAsString)} >
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() form.handleSubmit() }} > {#snippet children(field)} field.handleChange(details.valueAsString)} >
                    {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput(id: string): string; channelSliderTrack(id: ColorChannel): string; channelSliderT...` | No | The ids of the elements in the color picker. Useful for composition. | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether the color picker is inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `Color` | No | The v-model value of the color picker | | `name` | `string` | No | The name for the form input | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ColorPickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseColorPickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | | `ref` | `Element` | No | | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | | `ref` | `Element` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `dragging` | `boolean` | Whether the color picker is being dragged | | `open` | `boolean` | Whether the color picker is open | | `inline` | `boolean` | Whether the color picker is rendered inline | | `value` | `Color` | The current color value (as a string) | | `valueAsString` | `string` | The current color value (as a Color object) | | `setValue` | `(value: string | Color) => void` | Function to set the color value | | `getChannelValue` | `(channel: ColorChannel) => string` | Function to set the color value | | `getChannelValueText` | `(channel: ColorChannel, locale: string) => string` | Function to get the formatted and localized value of a specific channel | | `setChannelValue` | `(channel: ColorChannel, value: number) => void` | Function to set the color value of a specific channel | | `format` | `ColorFormat` | The current color format | | `setFormat` | `(format: ColorFormat) => void` | Function to set the color format | | `alpha` | `number` | The alpha value of the color | | `setAlpha` | `(value: number) => void` | Function to set the color alpha | | `setOpen` | `(open: boolean) => void` | Function to open or close the color picker | ## Accessibility ### Keyboard Support **`Enter`** Description: When focus is on the trigger, opens the color picker
                    When focus is on a trigger of a swatch, selects the color (and closes the color picker)
                    When focus is on the input or channel inputs, selects the color
                    **`ArrowLeft`** Description: When focus is on the color area, decreases the hue value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`ArrowRight`** Description: When focus is on the color area, increases the hue value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowUp`** Description: When focus is on the color area, increases the saturation value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowDown`** Description: When focus is on the color area, decreases the saturation value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`Esc`** Description: Closes the color picker and moves focus to the trigger # Color Picker (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Controlled Use the `value` and `onValueChange` props to programatically control the color picker's state. **Example: controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = useState(() => parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color.toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = createSignal(parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color().toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected color: {value.toString('hex')} Color
                    ``` ### Open Controlled Control the open state of the color picker popover programmatically using the `open` and `onOpenChange` props. **Example: open-controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = useState(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = createSignal(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color
                    ``` ### Root Provider An alternative way to control the color picker is to use the `RootProvider` component and the `useColorPicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker.valueAsString} Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker().valueAsString} Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color: {colorPicker().valueAsString} Color
                    {#each swatches as color} {/each}
                    ``` ### Disabled Use the `disabled` prop to disable the color picker. **Example: disabled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Inline Render the color picker inline without a popover by using the `inline` prop. **Example: inline** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each swatches as color} {/each} ``` ### Input Only A minimal color picker with just an input field, value swatch, and eye dropper trigger. **Example: input-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color ``` ### Slider Only Display only the channel sliders for RGB color selection. **Example: slider-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    R
                    G
                    B
                    ``` ### Swatch Only A simple color picker with only preset color swatches. **Example: swatch-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Selected color: {#each swatches as color} {/each} ``` ### Swatches Include preset color swatches in the color picker content for quick color selection. **Example: swatches** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    {#each swatches as color} {/each}
                    ``` ### Value Swatch Display the current color value as a swatch alongside the color area and sliders. **Example: value-swatch** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a color picker. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { Field } from '@ark-ui/react/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Field } from '@ark-ui/solid/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Additional Info Error Info
                    ``` ### Form Usage Integrate the color picker with form libraries like React Hook Form using the `HiddenInput` component. **Example: form-usage** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useForm } from 'react-hook-form' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' interface FieldValues { color: string } export const FormUsage = () => { const { register, handleSubmit } = useForm() const onSubmit = (data: FieldValues) => { alert(data) } return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { createForm, setValue } from '@modular-forms/solid' import { Pipette } from 'lucide-solid' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const FormUsage = () => { const [formStore, { Form, Field }] = createForm<{ color: string }>() return (
                    { window.alert(JSON.stringify(data)) }} > {(field) => ( setValue(formStore, 'color', details.valueAsString)} >
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() form.handleSubmit() }} > {#snippet children(field)} field.handleChange(details.valueAsString)} >
                    {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput(id: string): string; channelSliderTrack(id: ColorChannel): string; channelSliderT...` | No | The ids of the elements in the color picker. Useful for composition. | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether the color picker is inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `Color` | No | The v-model value of the color picker | | `name` | `string` | No | The name for the form input | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ColorPickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseColorPickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | | `ref` | `Element` | No | | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | | `ref` | `Element` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `dragging` | `boolean` | Whether the color picker is being dragged | | `open` | `boolean` | Whether the color picker is open | | `inline` | `boolean` | Whether the color picker is rendered inline | | `value` | `Color` | The current color value (as a string) | | `valueAsString` | `string` | The current color value (as a Color object) | | `setValue` | `(value: string | Color) => void` | Function to set the color value | | `getChannelValue` | `(channel: ColorChannel) => string` | Function to set the color value | | `getChannelValueText` | `(channel: ColorChannel, locale: string) => string` | Function to get the formatted and localized value of a specific channel | | `setChannelValue` | `(channel: ColorChannel, value: number) => void` | Function to set the color value of a specific channel | | `format` | `ColorFormat` | The current color format | | `setFormat` | `(format: ColorFormat) => void` | Function to set the color format | | `alpha` | `number` | The alpha value of the color | | `setAlpha` | `(value: number) => void` | Function to set the color alpha | | `setOpen` | `(open: boolean) => void` | Function to open or close the color picker | ## Accessibility ### Keyboard Support **`Enter`** Description: When focus is on the trigger, opens the color picker
                    When focus is on a trigger of a swatch, selects the color (and closes the color picker)
                    When focus is on the input or channel inputs, selects the color
                    **`ArrowLeft`** Description: When focus is on the color area, decreases the hue value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`ArrowRight`** Description: When focus is on the color area, increases the hue value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowUp`** Description: When focus is on the color area, increases the saturation value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowDown`** Description: When focus is on the color area, decreases the saturation value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`Esc`** Description: Closes the color picker and moves focus to the trigger # Color Picker (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const Basic = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Controlled Use the `value` and `onValueChange` props to programatically control the color picker's state. **Example: controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = useState(() => parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color.toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import styles from 'styles/color-picker.module.css' export const Controlled = () => { const [color, setColor] = createSignal(parseColor('hsl(20, 100%, 50%)')) return (
                    Selected color: {color().toString('hex')} setColor(e.value)}> Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Selected color: {value.toString('hex')} Color
                    ``` ### Open Controlled Control the open state of the color picker popover programmatically using the `open` and `onOpenChange` props. **Example: open-controlled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = useState(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import { createSignal } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const OpenControlled = () => { const [open, setOpen] = createSignal(false) return (
                    setOpen(e.open)} defaultValue={parseColor('#eb5e41')} > Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color
                    ``` ### Root Provider An alternative way to control the color picker is to use the `RootProvider` component and the `useColorPicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker.valueAsString} Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor, useColorPicker } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const RootProvider = () => { const colorPicker = useColorPicker({ defaultValue: parseColor('#eb5e41') }) return (
                    Color: {colorPicker().valueAsString} Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Color: {colorPicker().valueAsString} Color
                    {#each swatches as color} {/each}
                    ``` ### Disabled Use the `disabled` prop to disable the color picker. **Example: disabled** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const Disabled = () => { return ( Color
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    ``` ### Inline Render the color picker inline without a popover by using the `inline` prop. **Example: inline** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Inline = () => { return ( {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#each swatches as color} {/each} ``` ### Input Only A minimal color picker with just an input field, value swatch, and eye dropper trigger. **Example: input-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Pipette } from 'lucide-solid' import styles from 'styles/color-picker.module.css' export const InputOnly = () => { return ( Color ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color ``` ### Slider Only Display only the channel sliders for RGB color selection. **Example: slider-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const SliderOnly = () => { return (
                    R
                    G
                    B
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    R
                    G
                    B
                    ``` ### Swatch Only A simple color picker with only preset color swatches. **Example: swatch-only** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {swatches.map((color) => ( ))} ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'pink', 'orange', 'purple'] export const SwatchOnly = () => { return ( Selected color: {(color) => ( )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Selected color: {#each swatches as color} {/each} ``` ### Swatches Include preset color swatches in the color picker content for quick color selection. **Example: swatches** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { CheckIcon, PipetteIcon } from 'lucide-react' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {swatches.map((color) => ( ))}
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Check, Pipette } from 'lucide-solid' import { For } from 'solid-js' import styles from 'styles/color-picker.module.css' const swatches = ['red', 'blue', 'green', 'orange'] export const Swatches = () => { return ( Color
                    {(color) => ( )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Color
                    {#each swatches as color} {/each}
                    ``` ### Value Swatch Display the current color value as a swatch alongside the color area and sliders. **Example: value-swatch** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import styles from 'styles/color-picker.module.css' export const ValueSwatch = () => { return (
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a color picker. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { Field } from '@ark-ui/react/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { Field } from '@ark-ui/solid/field' import field from 'styles/field.module.css' import styles from 'styles/color-picker.module.css' export const WithField = () => ( Label
                    Additional Info Error Info
                    ) ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Additional Info Error Info
                    ``` ### Form Usage Integrate the color picker with form libraries like React Hook Form using the `HiddenInput` component. **Example: form-usage** #### React ```tsx import { ColorPicker, parseColor } from '@ark-ui/react/color-picker' import { PipetteIcon } from 'lucide-react' import { useForm } from 'react-hook-form' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' interface FieldValues { color: string } export const FormUsage = () => { const { register, handleSubmit } = useForm() const onSubmit = (data: FieldValues) => { alert(data) } return (
                    ) } ``` #### Solid ```tsx import { ColorPicker, parseColor } from '@ark-ui/solid/color-picker' import { createForm, setValue } from '@modular-forms/solid' import { Pipette } from 'lucide-solid' import button from 'styles/button.module.css' import styles from 'styles/color-picker.module.css' export const FormUsage = () => { const [formStore, { Form, Field }] = createForm<{ color: string }>() return (
                    { window.alert(JSON.stringify(data)) }} > {(field) => ( setValue(formStore, 'color', details.valueAsString)} >
                    )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    { e.preventDefault() form.handleSubmit() }} > {#snippet children(field)} field.handleChange(details.valueAsString)} >
                    {/snippet}
                    ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput(id: string): string; channelSliderTrack(id: ColorChannel): string; channelSliderT...` | No | The ids of the elements in the color picker. Useful for composition. | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether the color picker is inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `modelValue` | `Color` | No | The v-model value of the color picker | | `name` | `string` | No | The name for the form input | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `required` | `boolean` | No | Whether the color picker is required | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ColorPickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether to close the color picker when a swatch is selected | | `defaultFormat` | `ColorFormat` | No | The initial color format when rendered. Use when you don't need to control the color format of the color picker. | | `defaultOpen` | `boolean` | No | The initial open state of the color picker when rendered. Use when you don't need to control the open state of the color picker. | | `defaultValue` | `Color` | No | The initial color value when rendered. Use when you don't need to control the color value of the color picker. | | `disabled` | `boolean` | No | Whether the color picker is disabled | | `format` | `ColorFormat` | No | The controlled color format to use | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channe...` | No | The ids of the elements in the color picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `initialFocusEl` | `() => HTMLElement | null` | No | The initial focus element when the color picker is opened. | | `inline` | `boolean` | No | Whether to render the color picker inline | | `invalid` | `boolean` | No | Whether the color picker is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `name` | `string` | No | The name for the form input | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onFormatChange` | `(details: FormatChangeDetails) => void` | No | Function called when the color format changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Handler that is called when the user opens or closes the color picker. | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the value changes, as the user drags. | | `onValueChangeEnd` | `(details: ValueChangeDetails) => void` | No | Handler that is called when the user stops dragging. | | `open` | `boolean` | No | The controlled open state of the color picker | | `openAutoFocus` | `boolean` | No | Whether to auto focus the color picker when it is opened | | `positioning` | `PositioningOptions` | No | The positioning options for the color picker | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the color picker is read-only | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the color picker is required | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `Color` | No | The controlled color value of the color picker | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | root | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | **Root CSS Variables:** | Variable | Description | |----------|-------------| | `--value` | The current value | **AreaBackground Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaBackground Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-background | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **Area Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `xChannel` | `ColorChannel` | No | | | `yChannel` | `ColorChannel` | No | | **Area Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area | | `[data-invalid]` | Present when invalid | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **AreaThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **AreaThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | area-thumb | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **AreaThumb CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **ChannelInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ExtendedColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelInput Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-input | | `[data-channel]` | The color channel of the channelinput | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ChannelSliderLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderLabel Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-label | | `[data-channel]` | The color channel of the channelsliderlabel | **ChannelSlider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `channel` | `ColorChannel` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `orientation` | `Orientation` | No | | | `ref` | `Element` | No | | **ChannelSlider Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider | | `[data-channel]` | The color channel of the channelslider | | `[data-orientation]` | The orientation of the channelslider | **ChannelSliderThumb Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderThumb Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-thumb | | `[data-channel]` | The color channel of the channelsliderthumb | | `[data-disabled]` | Present when disabled | | `[data-orientation]` | The orientation of the channelsliderthumb | **ChannelSliderTrack Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderTrack Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-track | | `[data-channel]` | The color channel of the channelslidertrack | | `[data-orientation]` | The orientation of the channelslidertrack | **ChannelSliderValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ChannelSliderValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | channel-slider-value-text | | `[data-channel]` | The color channel of the channelslidervaluetext | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | content | | `[data-placement]` | The placement of the content | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-state]` | "open" | "closed" | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested color-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseColorPickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **EyeDropperTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **EyeDropperTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | eye-dropper-trigger | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **FormatSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **FormatTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **HiddenInput Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | label | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseColorPickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **SwatchGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **SwatchIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Swatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **Swatch Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | **Swatch CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **SwatchTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `string | Color` | Yes | The color value | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `disabled` | `boolean` | No | Whether the swatch trigger is disabled | | `ref` | `Element` | No | | **SwatchTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | swatch-trigger | | `[data-state]` | "checked" | "unchecked" | | `[data-value]` | The value of the item | | `[data-disabled]` | Present when disabled | **SwatchTrigger CSS Variables:** | Variable | Description | |----------|-------------| | `--color` | The text color | **TransparencyGrid Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `size` | `string` | No | | **TransparencyGrid CSS Variables:** | Variable | Description | |----------|-------------| | `--size` | The size (width and height) of the element | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | trigger | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | | `[data-invalid]` | Present when invalid | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | **ValueSwatch Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `respectAlpha` | `boolean` | No | Whether to include the alpha channel in the color | **ValueText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `format` | `ColorStringFormat` | No | | | `ref` | `Element` | No | | **ValueText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | color-picker | | `[data-part]` | value-text | | `[data-disabled]` | Present when disabled | | `[data-focus]` | Present when focused | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `format` | `ColorFormat` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `dragging` | `boolean` | Whether the color picker is being dragged | | `open` | `boolean` | Whether the color picker is open | | `inline` | `boolean` | Whether the color picker is rendered inline | | `value` | `Color` | The current color value (as a string) | | `valueAsString` | `string` | The current color value (as a Color object) | | `setValue` | `(value: string | Color) => void` | Function to set the color value | | `getChannelValue` | `(channel: ColorChannel) => string` | Function to set the color value | | `getChannelValueText` | `(channel: ColorChannel, locale: string) => string` | Function to get the formatted and localized value of a specific channel | | `setChannelValue` | `(channel: ColorChannel, value: number) => void` | Function to set the color value of a specific channel | | `format` | `ColorFormat` | The current color format | | `setFormat` | `(format: ColorFormat) => void` | Function to set the color format | | `alpha` | `number` | The alpha value of the color | | `setAlpha` | `(value: number) => void` | Function to set the color alpha | | `setOpen` | `(open: boolean) => void` | Function to open or close the color picker | ## Accessibility ### Keyboard Support **`Enter`** Description: When focus is on the trigger, opens the color picker
                    When focus is on a trigger of a swatch, selects the color (and closes the color picker)
                    When focus is on the input or channel inputs, selects the color
                    **`ArrowLeft`** Description: When focus is on the color area, decreases the hue value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`ArrowRight`** Description: When focus is on the color area, increases the hue value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowUp`** Description: When focus is on the color area, increases the saturation value of the color
                    When focus is on the channel sliders, increases the value of the channel
                    **`ArrowDown`** Description: When focus is on the color area, decreases the saturation value of the color
                    When focus is on the channel sliders, decreases the value of the channel
                    **`Esc`** Description: Closes the color picker and moves focus to the trigger # Combobox (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Basic = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Basic = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Fruit
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Auto Highlight Automatically highlight the first matching item as the user types by setting `inputBehavior="autohighlight"`. **Example: auto-highlight** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Inline Autocomplete Complete the input value with the first matching item by setting `inputBehavior="autocomplete"`. Use with `startsWith` filter for best results. **Example: inline-autocomplete** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: filterFn().startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Sea Creature
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Grouping To group related combobox items, use the `groupBy` prop on the collection and `collection.group()` to iterate the groups. **Example: grouping** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Grouping = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.group().map(([continent, group]) => ( {continent} {group.map((item) => ( {item.label} ))} ))}
                    ) } const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] export const Grouping = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {([continent, group]) => ( {continent} {(item) => ( {item.label} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().group() as [continent, group]} {continent} {#each group as item} {item.label} {/each} {/each}
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a combobox. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Field } from '@ark-ui/react/field' import { useFilter } from '@ark-ui/react/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' export const WithField = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    {collection.items.map((item) => ( {item.label} ))}
                    Select your primary department Department is required
                    ) } const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Field } from '@ark-ui/solid/field' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] export const WithField = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    {(item) => ( {item.label} )}
                    Select your primary department Department is required
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    Select your primary department Department is required
                    ``` ### Context Access the combobox's state with `Combobox.Context` or the `useComboboxContext` hook—useful for displaying the selected value or building custom UI. **Example: context** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Context = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(combobox) =>

                    Selected: {combobox.valueAsString || 'None'}

                    }
                    Size
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Context = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(context) =>

                    Selected: {context().valueAsString || 'None'}

                    }
                    Size
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(combobox)}

                    Selected: {combobox().valueAsString || 'None'}

                    {/snippet}
                    Size
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Root Provider An alternative way to control the combobox is to use the `RootProvider` component and the `useCombobox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const combobox = useCombobox({ collection, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const combobox = useCombobox({ get collection() { return collection() }, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Job Title
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Links Use the `asChild` prop to render the combobox items as links. **Example: links** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Links = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] export const Links = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {(item) => ( }> {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Developer Resources
                    Open
                    {#each collection().items as item (item.value)} {#snippet asChild(props)}
                    {item.label} {/snippet} {/each} ``` ### Rehydrate When a combobox has a `defaultValue` or `value` but the `collection` is not loaded yet, you can rehydrate the value to populate the input. **Example: rehydrate-value** #### React ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon } from 'lucide-react' import { useRef, useState } from 'react' import { useAsync } from 'react-use' import styles from 'styles/combobox.module.css' function ComboboxRehydrateValue() { const combobox = useComboboxContext() const hydrated = useRef(false) if (combobox.value.length && combobox.collection.size && !hydrated.current) { combobox.syncSelectedItems() hydrated.current = true } return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = useState('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox({ collection, defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue, onInputValueChange: (e) => setInputValue(e.inputValue), }) const state = useAsync(async () => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue}`) const data = await response.json() set(data.results) }, [inputValue, set]) return ( Search Star Wars Characters {state.loading ? ( Loading... ) : state.error ? ( {state.error.message} ) : ( collection.items.map((item) => ( {item.name} - {item.height}cm / {item.mass}kg )) )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Solid ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/solid/combobox' import { For, createEffect, createRenderEffect, createSignal, on } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' import { useAsync } from './use-async' function ComboboxRehydrateValue() { const combobox = useComboboxContext() let hydrated = false createRenderEffect(() => { if (combobox().value.length && combobox().collection.size && !hydrated) { combobox().syncSelectedItems() hydrated = true } }) return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = createSignal('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox(() => ({ collection: collection(), defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue: inputValue(), onInputValueChange: (e) => setInputValue(e.inputValue), })) const state = useAsync(async (signal) => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue()}`, { signal }) const data = await response.json() set(data.results) }) createEffect(on(inputValue, () => state.load())) return ( Search Star Wars Characters {state.loading() ? ( Loading... ) : state.error() ? ( {state.error()?.message} ) : ( {(item) => ( {item.name} - {item.height}cm / {item.mass}kg )} )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Vue ```vue ``` #### Svelte ```svelte Search Star Wars Characters {#if _state.loading()} Loading... {:else if _state.error()} {_state.error()?.message} {:else} {#each collection().items as item (item.name)} {item.name} - {item.height}cm / {item.mass}kg {/each} {/if} ``` ### Highlight Text Highlight the matching search text in combobox items based on the user's input. **Example: highlight-matching-text** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Highlight } from '@ark-ui/react/highlight' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    {collection.items.map((item) => ( {(context) => } ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Highlight } from '@ark-ui/solid/highlight' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    Clear Open
                    {(item) => ( {(context) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Assignee
                    Clear Open
                    {#each collection().items as item (item.value)} {#snippet render(context)} {/snippet} {/each}
                    ``` ### Dynamic Generate combobox items dynamically based on user input. This is useful for creating suggestions or autocomplete functionality. **Example: dynamic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    {collection.items.map((item) => ( {item} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    Open
                    {(item) => ( {item} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Email
                    Open
                    {#each collection().items as item (item)} {item} {/each}
                    ``` ### Creatable Allow users to create new options when their search doesn't match any existing items. This is useful for tags, categories, or other custom values. **Example: creatable** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import { useState } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection.filter((item) => item.toLowerCase() === inputValue.toLowerCase()).size > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = useState([]) const [inputValue, setInputValue] = useState('') const handleInputChange = ({ inputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { flushSync(() => { if (isValidNewOption(inputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(inputValue)) } else if (inputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } }) filter(inputValue) } setInputValue(inputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue)) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue) update(NEW_OPTION_VALUE, getNewOptionData(inputValue)) } } return ( Label
                    {collection.items.map((item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createSignal, For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: filterFn().contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection().items.filter((item) => item.label.toLowerCase() === inputValue.toLowerCase()).length > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = createSignal([]) const [inputValue, setInputValue] = createSignal('') const handleInputChange = ({ inputValue: newInputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { if (isValidNewOption(newInputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(newInputValue)) } else if (newInputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } filter(newInputValue) } setInputValue(newInputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue())) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue()) update(NEW_OPTION_VALUE, getNewOptionData(inputValue())) } } return ( Label
                    Clear Open
                    {(item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Clear Open
                    {#each collection().items as item (item.value)} {#if isNewOptionValue(item.value)} + Create "{item.label}" {:else} {item.label} {item.__new__ ? '(new)' : ''} {/if} {/each}
                    ``` ### Multiple Selection Enable multiple selection by setting the `multiple` prop. Selected items can be displayed as tags above the input. **Example: multiple** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import styles from 'styles/combobox.module.css' export const Multiple = () => { const { contains } = useFilter({ sensitivity: 'base' }) const selectedValue = useRef([]) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { selectedValue.current = details.value remove(...details.value) } return ( Skills {(combobox) => (
                    {combobox.selectedItems.length === 0 && None selected} {combobox.selectedItems.map((item: any) => ( {item.label} ))}
                    )}
                    No skills found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Multiple = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { remove(...details.value) } return ( Skills {(context) => (
                    {context().selectedItems.length === 0 && None selected} {(item: any) => {item.label}}
                    )}
                    No skills found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Skills
                    {#if selectedItems.length === 0} None selected {/if} {#each selectedItems as item (item.value)} {item.label} {/each}
                    Open
                    No skills found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Async Search Load options asynchronously based on user input using the `useAsyncList` hook. This is useful for searching large datasets or fetching data from an API. **Example: async-search** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { Combobox, createListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, LoaderIcon, XIcon } from 'lucide-react' import { startTransition } from 'react' import styles from 'styles/combobox.module.css' interface Movie { id: string title: string year: number director: string genre: string } export const AsyncSearch = () => { const list = useAsyncList({ async load({ filterText, signal }) { if (!filterText) return { items: [] } await new Promise((resolve) => setTimeout(resolve, 300)) if (signal?.aborted) return { items: [] } const items = allMovies.filter( (movie) => movie.title.toLowerCase().includes(filterText.toLowerCase()) || movie.director.toLowerCase().includes(filterText.toLowerCase()) || movie.genre.toLowerCase().includes(filterText.toLowerCase()), ) return { items } }, }) const collection = createListCollection({ items: list.items, itemToString: (item) => item.title, itemToValue: (item) => item.id, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { startTransition(() => { list.setFilterText(details.inputValue) }) } } return ( Movie
                    {list.loading ? (
                    Searching...
                    ) : list.error ? (
                    {list.error.message}
                    ) : list.items.length === 0 ? (
                    {list.filterText ? 'No results found' : 'Start typing to search movies...'}
                    ) : ( collection.items.map((movie) => ( {movie.title} {movie.year} · {movie.director} )) )}
                    ) } const allMovies: Movie[] = [ { id: 'inception', title: 'Inception', year: 2010, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'the-dark-knight', title: 'The Dark Knight', year: 2008, director: 'Christopher Nolan', genre: 'Action' }, { id: 'pulp-fiction', title: 'Pulp Fiction', year: 1994, director: 'Quentin Tarantino', genre: 'Crime' }, { id: 'the-godfather', title: 'The Godfather', year: 1972, director: 'Francis Ford Coppola', genre: 'Crime' }, { id: 'forrest-gump', title: 'Forrest Gump', year: 1994, director: 'Robert Zemeckis', genre: 'Drama' }, { id: 'the-matrix', title: 'The Matrix', year: 1999, director: 'The Wachowskis', genre: 'Sci-Fi' }, { id: 'interstellar', title: 'Interstellar', year: 2014, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'parasite', title: 'Parasite', year: 2019, director: 'Bong Joon-ho', genre: 'Thriller' }, { id: 'the-shawshank-redemption', title: 'The Shawshank Redemption', year: 1994, director: 'Frank Darabont', genre: 'Drama', }, { id: 'fight-club', title: 'Fight Club', year: 1999, director: 'David Fincher', genre: 'Drama' }, { id: 'goodfellas', title: 'Goodfellas', year: 1990, director: 'Martin Scorsese', genre: 'Crime' }, { id: 'the-silence-of-the-lambs', title: 'The Silence of the Lambs', year: 1991, director: 'Jonathan Demme', genre: 'Thriller', }, ] ``` ### Virtualized For very large lists, use virtualization with `@tanstack/virtual` to render only the visible items. Pass the `scrollToIndexFn` prop to enable keyboard navigation within the virtualized list. **Example: virtualized** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { useVirtualizer } from '@tanstack/react-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' export const Virtualized = () => { const contentRef = useRef(null) const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: startsWith, }) const virtualizer = useVirtualizer({ count: collection.size, getScrollElement: () => contentRef.current, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { flushSync(() => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection.items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createVirtualizer } from '@tanstack/solid-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Virtualized = () => { let contentRef: HTMLDivElement | undefined const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: filterFn().startsWith, }) const virtualizer = createVirtualizer({ get count() { return collection().size }, getScrollElement: () => contentRef ?? null, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection().items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Open
                    {#each $virtualizer.getVirtualItems() as virtualItem (virtualItem.key)} {@const item = collection().items[virtualItem.index]} {item.label} {/each}
                    ``` ### Custom Object Use the `itemToString` and `itemToValue` props to map custom objects to the required interface. **Example: custom-object** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.items.map((item) => ( {item.flag} {item.country} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    Clear Open
                    {(item) => ( {item.flag} {item.country} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().items as item (item.code)} {item.flag} {item.country} {/each}
                    ``` ### Limit Results Use the `limit` property on `useListCollection` to limit the number of rendered items in the DOM. **Example: limit-results** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    Open
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte City
                    Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ## Guides ### Router Links Customize the `navigate` prop on `Combobox.Root` to integrate with your router. Using Tanstack Router: ```tsx import { Combobox } from '@ark-ui//combobox' import { useNavigate } from '@tanstack/react-router' function Demo() { const navigate = useNavigate() return ( { navigate({ to: e.node.href }) }} > {/* ... */} ) } ``` ### Custom Objects By default, the combobox collection expects an array of objects with `label` and `value` properties. In some cases, you may need to deal with custom objects. Use the `itemToString` and `itemToValue` props to map the custom object to the required interface. ```tsx const items = [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, // ... ] const { collection } = useListCollection({ initialItems: items, itemToString: (item) => item.country, itemToValue: (item) => item.code, }) ``` ### Type Safety The `Combobox.RootComponent` type enables you to create typed wrapper components that maintain full type safety for collection items. ```tsx const Combobox: ArkCombobox.RootComponent = (props) => { return {/* ... */} } ``` Use the wrapper with full type inference on `onValueChange` and other callbacks: ```tsx const App = () => { const { collection } = useListCollection({ initialItems: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, ], }) return ( { // e.items is typed as Array<{ label: string, value: string }> console.log(e.items) }} > {/* ... */} ) } ``` ### Large Datasets The recommended way of managing large lists is to use the `limit` property on the `useListCollection` hook. This will limit the number of rendered items in the DOM to improve performance. ```tsx {3} const { collection } = useListCollection({ initialItems: items, limit: 10, }) ``` ### Available Size The following css variables are exposed to the `Combobox.Positioner` which you can use to style the `Combobox.Content` ```css /* width of the combobox control */ --reference-width: ; /* width of the available viewport */ --available-width: ; /* height of the available viewport */ --available-height: ; ``` For example, if you want to make sure the maximum height doesn't exceed the available height, you can use the following: ```css [data-scope='combobox'][data-part='content'] { max-height: calc(var(--available-height) - 100px); } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether 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. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `collection` | `ListCollection` | No | The collection of items | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item(id: string, index?: number | undefined): string positioner: string itemGroup(id: string | number): string itemGroupLabel(id: string | number): string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `modelValue` | `string[]` | No | The v-model value of the combobox | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ComboboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `MaybeFunction>` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autocomplete' | 'autohighlight'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxItemContext]>` | Yes | | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `{}` | No | | | `persistFocus` | `boolean` | No | | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the combobox is focused | | `open` | `boolean` | Whether the combobox is open | | `inputValue` | `string` | The value of the combobox input | | `highlightedValue` | `string` | The value of the highlighted item | | `highlightedItem` | `V` | The highlighted item | | `setHighlightValue` | `(value: string) => void` | The value of the combobox input | | `clearHighlightValue` | `VoidFunction` | Function to clear the highlighted value | | `syncSelectedItems` | `VoidFunction` | Function to sync the selected items with the value. Useful when `value` is updated from async sources. | | `selectedItems` | `V[]` | The selected items | | `hasSelectedItems` | `boolean` | Whether there's a selected item | | `value` | `string[]` | The selected item keys | | `valueAsString` | `string` | The string representation of the selected items | | `selectValue` | `(value: string) => void` | Function to select a value | | `setValue` | `(value: string[]) => void` | Function to set the value of the combobox | | `clearValue` | `(value?: string) => void` | Function to clear the value of the combobox | | `focus` | `VoidFunction` | Function to focus on the combobox input | | `setInputValue` | `(value: string, reason?: InputValueChangeReason) => void` | Function to set the input value of the combobox | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a combobox item | | `setOpen` | `(open: boolean, reason?: OpenChangeReason) => void` | Function to open or close the combobox | | `collection` | `ListCollection` | Function to toggle the combobox | | `reposition` | `(options?: Partial) => void` | Function to set the positioning options | | `multiple` | `boolean` | Whether the combobox allows multiple selections | | `disabled` | `boolean` | Whether the combobox is disabled | ## Accessibility Complies with the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). ### Keyboard Support **`ArrowDown`** Description: When the combobox is closed, opens the listbox and highlights to the first option. When the combobox is open, moves focus to the next option. **`ArrowUp`** Description: When the combobox is closed, opens the listbox and highlights to the last option. When the combobox is open, moves focus to the previous option. **`Home`** Description: When the combobox is open, moves focus to the first option. **`End`** Description: When the combobox is open, moves focus to the last option. **`Escape`** Description: Closes the listbox. **`Enter`** Description: Selects the highlighted option and closes the combobox. **`Esc`** Description: Closes the combobox # Combobox (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Basic = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Basic = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Fruit
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Auto Highlight Automatically highlight the first matching item as the user types by setting `inputBehavior="autohighlight"`. **Example: auto-highlight** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Inline Autocomplete Complete the input value with the first matching item by setting `inputBehavior="autocomplete"`. Use with `startsWith` filter for best results. **Example: inline-autocomplete** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: filterFn().startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Sea Creature
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Grouping To group related combobox items, use the `groupBy` prop on the collection and `collection.group()` to iterate the groups. **Example: grouping** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Grouping = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.group().map(([continent, group]) => ( {continent} {group.map((item) => ( {item.label} ))} ))}
                    ) } const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] export const Grouping = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {([continent, group]) => ( {continent} {(item) => ( {item.label} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().group() as [continent, group]} {continent} {#each group as item} {item.label} {/each} {/each}
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a combobox. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Field } from '@ark-ui/react/field' import { useFilter } from '@ark-ui/react/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' export const WithField = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    {collection.items.map((item) => ( {item.label} ))}
                    Select your primary department Department is required
                    ) } const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Field } from '@ark-ui/solid/field' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] export const WithField = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    {(item) => ( {item.label} )}
                    Select your primary department Department is required
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    Select your primary department Department is required
                    ``` ### Context Access the combobox's state with `Combobox.Context` or the `useComboboxContext` hook—useful for displaying the selected value or building custom UI. **Example: context** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Context = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(combobox) =>

                    Selected: {combobox.valueAsString || 'None'}

                    }
                    Size
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Context = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(context) =>

                    Selected: {context().valueAsString || 'None'}

                    }
                    Size
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(combobox)}

                    Selected: {combobox().valueAsString || 'None'}

                    {/snippet}
                    Size
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Root Provider An alternative way to control the combobox is to use the `RootProvider` component and the `useCombobox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const combobox = useCombobox({ collection, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const combobox = useCombobox({ get collection() { return collection() }, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Job Title
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Links Use the `asChild` prop to render the combobox items as links. **Example: links** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Links = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] export const Links = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {(item) => ( }> {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Developer Resources
                    Open
                    {#each collection().items as item (item.value)} {#snippet asChild(props)}
                    {item.label} {/snippet} {/each} ``` ### Rehydrate When a combobox has a `defaultValue` or `value` but the `collection` is not loaded yet, you can rehydrate the value to populate the input. **Example: rehydrate-value** #### React ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon } from 'lucide-react' import { useRef, useState } from 'react' import { useAsync } from 'react-use' import styles from 'styles/combobox.module.css' function ComboboxRehydrateValue() { const combobox = useComboboxContext() const hydrated = useRef(false) if (combobox.value.length && combobox.collection.size && !hydrated.current) { combobox.syncSelectedItems() hydrated.current = true } return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = useState('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox({ collection, defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue, onInputValueChange: (e) => setInputValue(e.inputValue), }) const state = useAsync(async () => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue}`) const data = await response.json() set(data.results) }, [inputValue, set]) return ( Search Star Wars Characters {state.loading ? ( Loading... ) : state.error ? ( {state.error.message} ) : ( collection.items.map((item) => ( {item.name} - {item.height}cm / {item.mass}kg )) )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Solid ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/solid/combobox' import { For, createEffect, createRenderEffect, createSignal, on } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' import { useAsync } from './use-async' function ComboboxRehydrateValue() { const combobox = useComboboxContext() let hydrated = false createRenderEffect(() => { if (combobox().value.length && combobox().collection.size && !hydrated) { combobox().syncSelectedItems() hydrated = true } }) return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = createSignal('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox(() => ({ collection: collection(), defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue: inputValue(), onInputValueChange: (e) => setInputValue(e.inputValue), })) const state = useAsync(async (signal) => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue()}`, { signal }) const data = await response.json() set(data.results) }) createEffect(on(inputValue, () => state.load())) return ( Search Star Wars Characters {state.loading() ? ( Loading... ) : state.error() ? ( {state.error()?.message} ) : ( {(item) => ( {item.name} - {item.height}cm / {item.mass}kg )} )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Vue ```vue ``` #### Svelte ```svelte Search Star Wars Characters {#if _state.loading()} Loading... {:else if _state.error()} {_state.error()?.message} {:else} {#each collection().items as item (item.name)} {item.name} - {item.height}cm / {item.mass}kg {/each} {/if} ``` ### Highlight Text Highlight the matching search text in combobox items based on the user's input. **Example: highlight-matching-text** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Highlight } from '@ark-ui/react/highlight' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    {collection.items.map((item) => ( {(context) => } ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Highlight } from '@ark-ui/solid/highlight' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    Clear Open
                    {(item) => ( {(context) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Assignee
                    Clear Open
                    {#each collection().items as item (item.value)} {#snippet render(context)} {/snippet} {/each}
                    ``` ### Dynamic Generate combobox items dynamically based on user input. This is useful for creating suggestions or autocomplete functionality. **Example: dynamic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    {collection.items.map((item) => ( {item} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    Open
                    {(item) => ( {item} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Email
                    Open
                    {#each collection().items as item (item)} {item} {/each}
                    ``` ### Creatable Allow users to create new options when their search doesn't match any existing items. This is useful for tags, categories, or other custom values. **Example: creatable** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import { useState } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection.filter((item) => item.toLowerCase() === inputValue.toLowerCase()).size > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = useState([]) const [inputValue, setInputValue] = useState('') const handleInputChange = ({ inputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { flushSync(() => { if (isValidNewOption(inputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(inputValue)) } else if (inputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } }) filter(inputValue) } setInputValue(inputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue)) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue) update(NEW_OPTION_VALUE, getNewOptionData(inputValue)) } } return ( Label
                    {collection.items.map((item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createSignal, For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: filterFn().contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection().items.filter((item) => item.label.toLowerCase() === inputValue.toLowerCase()).length > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = createSignal([]) const [inputValue, setInputValue] = createSignal('') const handleInputChange = ({ inputValue: newInputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { if (isValidNewOption(newInputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(newInputValue)) } else if (newInputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } filter(newInputValue) } setInputValue(newInputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue())) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue()) update(NEW_OPTION_VALUE, getNewOptionData(inputValue())) } } return ( Label
                    Clear Open
                    {(item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Clear Open
                    {#each collection().items as item (item.value)} {#if isNewOptionValue(item.value)} + Create "{item.label}" {:else} {item.label} {item.__new__ ? '(new)' : ''} {/if} {/each}
                    ``` ### Multiple Selection Enable multiple selection by setting the `multiple` prop. Selected items can be displayed as tags above the input. **Example: multiple** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import styles from 'styles/combobox.module.css' export const Multiple = () => { const { contains } = useFilter({ sensitivity: 'base' }) const selectedValue = useRef([]) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { selectedValue.current = details.value remove(...details.value) } return ( Skills {(combobox) => (
                    {combobox.selectedItems.length === 0 && None selected} {combobox.selectedItems.map((item: any) => ( {item.label} ))}
                    )}
                    No skills found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Multiple = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { remove(...details.value) } return ( Skills {(context) => (
                    {context().selectedItems.length === 0 && None selected} {(item: any) => {item.label}}
                    )}
                    No skills found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Skills
                    {#if selectedItems.length === 0} None selected {/if} {#each selectedItems as item (item.value)} {item.label} {/each}
                    Open
                    No skills found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Async Search Load options asynchronously based on user input using the `useAsyncList` hook. This is useful for searching large datasets or fetching data from an API. **Example: async-search** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { Combobox, createListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, LoaderIcon, XIcon } from 'lucide-react' import { startTransition } from 'react' import styles from 'styles/combobox.module.css' interface Movie { id: string title: string year: number director: string genre: string } export const AsyncSearch = () => { const list = useAsyncList({ async load({ filterText, signal }) { if (!filterText) return { items: [] } await new Promise((resolve) => setTimeout(resolve, 300)) if (signal?.aborted) return { items: [] } const items = allMovies.filter( (movie) => movie.title.toLowerCase().includes(filterText.toLowerCase()) || movie.director.toLowerCase().includes(filterText.toLowerCase()) || movie.genre.toLowerCase().includes(filterText.toLowerCase()), ) return { items } }, }) const collection = createListCollection({ items: list.items, itemToString: (item) => item.title, itemToValue: (item) => item.id, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { startTransition(() => { list.setFilterText(details.inputValue) }) } } return ( Movie
                    {list.loading ? (
                    Searching...
                    ) : list.error ? (
                    {list.error.message}
                    ) : list.items.length === 0 ? (
                    {list.filterText ? 'No results found' : 'Start typing to search movies...'}
                    ) : ( collection.items.map((movie) => ( {movie.title} {movie.year} · {movie.director} )) )}
                    ) } const allMovies: Movie[] = [ { id: 'inception', title: 'Inception', year: 2010, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'the-dark-knight', title: 'The Dark Knight', year: 2008, director: 'Christopher Nolan', genre: 'Action' }, { id: 'pulp-fiction', title: 'Pulp Fiction', year: 1994, director: 'Quentin Tarantino', genre: 'Crime' }, { id: 'the-godfather', title: 'The Godfather', year: 1972, director: 'Francis Ford Coppola', genre: 'Crime' }, { id: 'forrest-gump', title: 'Forrest Gump', year: 1994, director: 'Robert Zemeckis', genre: 'Drama' }, { id: 'the-matrix', title: 'The Matrix', year: 1999, director: 'The Wachowskis', genre: 'Sci-Fi' }, { id: 'interstellar', title: 'Interstellar', year: 2014, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'parasite', title: 'Parasite', year: 2019, director: 'Bong Joon-ho', genre: 'Thriller' }, { id: 'the-shawshank-redemption', title: 'The Shawshank Redemption', year: 1994, director: 'Frank Darabont', genre: 'Drama', }, { id: 'fight-club', title: 'Fight Club', year: 1999, director: 'David Fincher', genre: 'Drama' }, { id: 'goodfellas', title: 'Goodfellas', year: 1990, director: 'Martin Scorsese', genre: 'Crime' }, { id: 'the-silence-of-the-lambs', title: 'The Silence of the Lambs', year: 1991, director: 'Jonathan Demme', genre: 'Thriller', }, ] ``` ### Virtualized For very large lists, use virtualization with `@tanstack/virtual` to render only the visible items. Pass the `scrollToIndexFn` prop to enable keyboard navigation within the virtualized list. **Example: virtualized** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { useVirtualizer } from '@tanstack/react-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' export const Virtualized = () => { const contentRef = useRef(null) const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: startsWith, }) const virtualizer = useVirtualizer({ count: collection.size, getScrollElement: () => contentRef.current, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { flushSync(() => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection.items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createVirtualizer } from '@tanstack/solid-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Virtualized = () => { let contentRef: HTMLDivElement | undefined const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: filterFn().startsWith, }) const virtualizer = createVirtualizer({ get count() { return collection().size }, getScrollElement: () => contentRef ?? null, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection().items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Open
                    {#each $virtualizer.getVirtualItems() as virtualItem (virtualItem.key)} {@const item = collection().items[virtualItem.index]} {item.label} {/each}
                    ``` ### Custom Object Use the `itemToString` and `itemToValue` props to map custom objects to the required interface. **Example: custom-object** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.items.map((item) => ( {item.flag} {item.country} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    Clear Open
                    {(item) => ( {item.flag} {item.country} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().items as item (item.code)} {item.flag} {item.country} {/each}
                    ``` ### Limit Results Use the `limit` property on `useListCollection` to limit the number of rendered items in the DOM. **Example: limit-results** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    Open
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte City
                    Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ## Guides ### Router Links Customize the `navigate` prop on `Combobox.Root` to integrate with your router. Using Tanstack Router: ```tsx import { Combobox } from '@ark-ui//combobox' import { useNavigate } from '@tanstack/react-router' function Demo() { const navigate = useNavigate() return ( { navigate({ to: e.node.href }) }} > {/* ... */} ) } ``` ### Custom Objects By default, the combobox collection expects an array of objects with `label` and `value` properties. In some cases, you may need to deal with custom objects. Use the `itemToString` and `itemToValue` props to map the custom object to the required interface. ```tsx const items = [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, // ... ] const { collection } = useListCollection({ initialItems: items, itemToString: (item) => item.country, itemToValue: (item) => item.code, }) ``` ### Type Safety The `Combobox.RootComponent` type enables you to create typed wrapper components that maintain full type safety for collection items. ```tsx const Combobox: ArkCombobox.RootComponent = (props) => { return {/* ... */} } ``` Use the wrapper with full type inference on `onValueChange` and other callbacks: ```tsx const App = () => { const { collection } = useListCollection({ initialItems: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, ], }) return ( { // e.items is typed as Array<{ label: string, value: string }> console.log(e.items) }} > {/* ... */} ) } ``` ### Large Datasets The recommended way of managing large lists is to use the `limit` property on the `useListCollection` hook. This will limit the number of rendered items in the DOM to improve performance. ```tsx {3} const { collection } = useListCollection({ initialItems: items, limit: 10, }) ``` ### Available Size The following css variables are exposed to the `Combobox.Positioner` which you can use to style the `Combobox.Content` ```css /* width of the combobox control */ --reference-width: ; /* width of the available viewport */ --available-width: ; /* height of the available viewport */ --available-height: ; ``` For example, if you want to make sure the maximum height doesn't exceed the available height, you can use the following: ```css [data-scope='combobox'][data-part='content'] { max-height: calc(var(--available-height) - 100px); } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether 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. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `collection` | `ListCollection` | No | The collection of items | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item(id: string, index?: number | undefined): string positioner: string itemGroup(id: string | number): string itemGroupLabel(id: string | number): string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `modelValue` | `string[]` | No | The v-model value of the combobox | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ComboboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `MaybeFunction>` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autocomplete' | 'autohighlight'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxItemContext]>` | Yes | | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `{}` | No | | | `persistFocus` | `boolean` | No | | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the combobox is focused | | `open` | `boolean` | Whether the combobox is open | | `inputValue` | `string` | The value of the combobox input | | `highlightedValue` | `string` | The value of the highlighted item | | `highlightedItem` | `V` | The highlighted item | | `setHighlightValue` | `(value: string) => void` | The value of the combobox input | | `clearHighlightValue` | `VoidFunction` | Function to clear the highlighted value | | `syncSelectedItems` | `VoidFunction` | Function to sync the selected items with the value. Useful when `value` is updated from async sources. | | `selectedItems` | `V[]` | The selected items | | `hasSelectedItems` | `boolean` | Whether there's a selected item | | `value` | `string[]` | The selected item keys | | `valueAsString` | `string` | The string representation of the selected items | | `selectValue` | `(value: string) => void` | Function to select a value | | `setValue` | `(value: string[]) => void` | Function to set the value of the combobox | | `clearValue` | `(value?: string) => void` | Function to clear the value of the combobox | | `focus` | `VoidFunction` | Function to focus on the combobox input | | `setInputValue` | `(value: string, reason?: InputValueChangeReason) => void` | Function to set the input value of the combobox | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a combobox item | | `setOpen` | `(open: boolean, reason?: OpenChangeReason) => void` | Function to open or close the combobox | | `collection` | `ListCollection` | Function to toggle the combobox | | `reposition` | `(options?: Partial) => void` | Function to set the positioning options | | `multiple` | `boolean` | Whether the combobox allows multiple selections | | `disabled` | `boolean` | Whether the combobox is disabled | ## Accessibility Complies with the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). ### Keyboard Support **`ArrowDown`** Description: When the combobox is closed, opens the listbox and highlights to the first option. When the combobox is open, moves focus to the next option. **`ArrowUp`** Description: When the combobox is closed, opens the listbox and highlights to the last option. When the combobox is open, moves focus to the previous option. **`Home`** Description: When the combobox is open, moves focus to the first option. **`End`** Description: When the combobox is open, moves focus to the last option. **`Escape`** Description: Closes the listbox. **`Enter`** Description: Selects the highlighted option and closes the combobox. **`Esc`** Description: Closes the combobox # Combobox (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Basic = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Basic = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Fruit
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Auto Highlight Automatically highlight the first matching item as the user types by setting `inputBehavior="autohighlight"`. **Example: auto-highlight** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Inline Autocomplete Complete the input value with the first matching item by setting `inputBehavior="autocomplete"`. Use with `startsWith` filter for best results. **Example: inline-autocomplete** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: filterFn().startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Sea Creature
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Grouping To group related combobox items, use the `groupBy` prop on the collection and `collection.group()` to iterate the groups. **Example: grouping** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Grouping = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.group().map(([continent, group]) => ( {continent} {group.map((item) => ( {item.label} ))} ))}
                    ) } const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] export const Grouping = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {([continent, group]) => ( {continent} {(item) => ( {item.label} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().group() as [continent, group]} {continent} {#each group as item} {item.label} {/each} {/each}
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a combobox. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Field } from '@ark-ui/react/field' import { useFilter } from '@ark-ui/react/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' export const WithField = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    {collection.items.map((item) => ( {item.label} ))}
                    Select your primary department Department is required
                    ) } const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Field } from '@ark-ui/solid/field' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] export const WithField = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    {(item) => ( {item.label} )}
                    Select your primary department Department is required
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    Select your primary department Department is required
                    ``` ### Context Access the combobox's state with `Combobox.Context` or the `useComboboxContext` hook—useful for displaying the selected value or building custom UI. **Example: context** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Context = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(combobox) =>

                    Selected: {combobox.valueAsString || 'None'}

                    }
                    Size
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Context = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(context) =>

                    Selected: {context().valueAsString || 'None'}

                    }
                    Size
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(combobox)}

                    Selected: {combobox().valueAsString || 'None'}

                    {/snippet}
                    Size
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Root Provider An alternative way to control the combobox is to use the `RootProvider` component and the `useCombobox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const combobox = useCombobox({ collection, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const combobox = useCombobox({ get collection() { return collection() }, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Job Title
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Links Use the `asChild` prop to render the combobox items as links. **Example: links** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Links = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] export const Links = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {(item) => ( }> {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Developer Resources
                    Open
                    {#each collection().items as item (item.value)} {#snippet asChild(props)}
                    {item.label} {/snippet} {/each} ``` ### Rehydrate When a combobox has a `defaultValue` or `value` but the `collection` is not loaded yet, you can rehydrate the value to populate the input. **Example: rehydrate-value** #### React ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon } from 'lucide-react' import { useRef, useState } from 'react' import { useAsync } from 'react-use' import styles from 'styles/combobox.module.css' function ComboboxRehydrateValue() { const combobox = useComboboxContext() const hydrated = useRef(false) if (combobox.value.length && combobox.collection.size && !hydrated.current) { combobox.syncSelectedItems() hydrated.current = true } return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = useState('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox({ collection, defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue, onInputValueChange: (e) => setInputValue(e.inputValue), }) const state = useAsync(async () => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue}`) const data = await response.json() set(data.results) }, [inputValue, set]) return ( Search Star Wars Characters {state.loading ? ( Loading... ) : state.error ? ( {state.error.message} ) : ( collection.items.map((item) => ( {item.name} - {item.height}cm / {item.mass}kg )) )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Solid ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/solid/combobox' import { For, createEffect, createRenderEffect, createSignal, on } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' import { useAsync } from './use-async' function ComboboxRehydrateValue() { const combobox = useComboboxContext() let hydrated = false createRenderEffect(() => { if (combobox().value.length && combobox().collection.size && !hydrated) { combobox().syncSelectedItems() hydrated = true } }) return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = createSignal('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox(() => ({ collection: collection(), defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue: inputValue(), onInputValueChange: (e) => setInputValue(e.inputValue), })) const state = useAsync(async (signal) => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue()}`, { signal }) const data = await response.json() set(data.results) }) createEffect(on(inputValue, () => state.load())) return ( Search Star Wars Characters {state.loading() ? ( Loading... ) : state.error() ? ( {state.error()?.message} ) : ( {(item) => ( {item.name} - {item.height}cm / {item.mass}kg )} )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Vue ```vue ``` #### Svelte ```svelte Search Star Wars Characters {#if _state.loading()} Loading... {:else if _state.error()} {_state.error()?.message} {:else} {#each collection().items as item (item.name)} {item.name} - {item.height}cm / {item.mass}kg {/each} {/if} ``` ### Highlight Text Highlight the matching search text in combobox items based on the user's input. **Example: highlight-matching-text** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Highlight } from '@ark-ui/react/highlight' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    {collection.items.map((item) => ( {(context) => } ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Highlight } from '@ark-ui/solid/highlight' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    Clear Open
                    {(item) => ( {(context) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Assignee
                    Clear Open
                    {#each collection().items as item (item.value)} {#snippet render(context)} {/snippet} {/each}
                    ``` ### Dynamic Generate combobox items dynamically based on user input. This is useful for creating suggestions or autocomplete functionality. **Example: dynamic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    {collection.items.map((item) => ( {item} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    Open
                    {(item) => ( {item} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Email
                    Open
                    {#each collection().items as item (item)} {item} {/each}
                    ``` ### Creatable Allow users to create new options when their search doesn't match any existing items. This is useful for tags, categories, or other custom values. **Example: creatable** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import { useState } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection.filter((item) => item.toLowerCase() === inputValue.toLowerCase()).size > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = useState([]) const [inputValue, setInputValue] = useState('') const handleInputChange = ({ inputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { flushSync(() => { if (isValidNewOption(inputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(inputValue)) } else if (inputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } }) filter(inputValue) } setInputValue(inputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue)) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue) update(NEW_OPTION_VALUE, getNewOptionData(inputValue)) } } return ( Label
                    {collection.items.map((item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createSignal, For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: filterFn().contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection().items.filter((item) => item.label.toLowerCase() === inputValue.toLowerCase()).length > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = createSignal([]) const [inputValue, setInputValue] = createSignal('') const handleInputChange = ({ inputValue: newInputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { if (isValidNewOption(newInputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(newInputValue)) } else if (newInputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } filter(newInputValue) } setInputValue(newInputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue())) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue()) update(NEW_OPTION_VALUE, getNewOptionData(inputValue())) } } return ( Label
                    Clear Open
                    {(item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Clear Open
                    {#each collection().items as item (item.value)} {#if isNewOptionValue(item.value)} + Create "{item.label}" {:else} {item.label} {item.__new__ ? '(new)' : ''} {/if} {/each}
                    ``` ### Multiple Selection Enable multiple selection by setting the `multiple` prop. Selected items can be displayed as tags above the input. **Example: multiple** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import styles from 'styles/combobox.module.css' export const Multiple = () => { const { contains } = useFilter({ sensitivity: 'base' }) const selectedValue = useRef([]) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { selectedValue.current = details.value remove(...details.value) } return ( Skills {(combobox) => (
                    {combobox.selectedItems.length === 0 && None selected} {combobox.selectedItems.map((item: any) => ( {item.label} ))}
                    )}
                    No skills found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Multiple = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { remove(...details.value) } return ( Skills {(context) => (
                    {context().selectedItems.length === 0 && None selected} {(item: any) => {item.label}}
                    )}
                    No skills found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Skills
                    {#if selectedItems.length === 0} None selected {/if} {#each selectedItems as item (item.value)} {item.label} {/each}
                    Open
                    No skills found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Async Search Load options asynchronously based on user input using the `useAsyncList` hook. This is useful for searching large datasets or fetching data from an API. **Example: async-search** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { Combobox, createListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, LoaderIcon, XIcon } from 'lucide-react' import { startTransition } from 'react' import styles from 'styles/combobox.module.css' interface Movie { id: string title: string year: number director: string genre: string } export const AsyncSearch = () => { const list = useAsyncList({ async load({ filterText, signal }) { if (!filterText) return { items: [] } await new Promise((resolve) => setTimeout(resolve, 300)) if (signal?.aborted) return { items: [] } const items = allMovies.filter( (movie) => movie.title.toLowerCase().includes(filterText.toLowerCase()) || movie.director.toLowerCase().includes(filterText.toLowerCase()) || movie.genre.toLowerCase().includes(filterText.toLowerCase()), ) return { items } }, }) const collection = createListCollection({ items: list.items, itemToString: (item) => item.title, itemToValue: (item) => item.id, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { startTransition(() => { list.setFilterText(details.inputValue) }) } } return ( Movie
                    {list.loading ? (
                    Searching...
                    ) : list.error ? (
                    {list.error.message}
                    ) : list.items.length === 0 ? (
                    {list.filterText ? 'No results found' : 'Start typing to search movies...'}
                    ) : ( collection.items.map((movie) => ( {movie.title} {movie.year} · {movie.director} )) )}
                    ) } const allMovies: Movie[] = [ { id: 'inception', title: 'Inception', year: 2010, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'the-dark-knight', title: 'The Dark Knight', year: 2008, director: 'Christopher Nolan', genre: 'Action' }, { id: 'pulp-fiction', title: 'Pulp Fiction', year: 1994, director: 'Quentin Tarantino', genre: 'Crime' }, { id: 'the-godfather', title: 'The Godfather', year: 1972, director: 'Francis Ford Coppola', genre: 'Crime' }, { id: 'forrest-gump', title: 'Forrest Gump', year: 1994, director: 'Robert Zemeckis', genre: 'Drama' }, { id: 'the-matrix', title: 'The Matrix', year: 1999, director: 'The Wachowskis', genre: 'Sci-Fi' }, { id: 'interstellar', title: 'Interstellar', year: 2014, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'parasite', title: 'Parasite', year: 2019, director: 'Bong Joon-ho', genre: 'Thriller' }, { id: 'the-shawshank-redemption', title: 'The Shawshank Redemption', year: 1994, director: 'Frank Darabont', genre: 'Drama', }, { id: 'fight-club', title: 'Fight Club', year: 1999, director: 'David Fincher', genre: 'Drama' }, { id: 'goodfellas', title: 'Goodfellas', year: 1990, director: 'Martin Scorsese', genre: 'Crime' }, { id: 'the-silence-of-the-lambs', title: 'The Silence of the Lambs', year: 1991, director: 'Jonathan Demme', genre: 'Thriller', }, ] ``` ### Virtualized For very large lists, use virtualization with `@tanstack/virtual` to render only the visible items. Pass the `scrollToIndexFn` prop to enable keyboard navigation within the virtualized list. **Example: virtualized** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { useVirtualizer } from '@tanstack/react-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' export const Virtualized = () => { const contentRef = useRef(null) const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: startsWith, }) const virtualizer = useVirtualizer({ count: collection.size, getScrollElement: () => contentRef.current, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { flushSync(() => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection.items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createVirtualizer } from '@tanstack/solid-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Virtualized = () => { let contentRef: HTMLDivElement | undefined const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: filterFn().startsWith, }) const virtualizer = createVirtualizer({ get count() { return collection().size }, getScrollElement: () => contentRef ?? null, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection().items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Open
                    {#each $virtualizer.getVirtualItems() as virtualItem (virtualItem.key)} {@const item = collection().items[virtualItem.index]} {item.label} {/each}
                    ``` ### Custom Object Use the `itemToString` and `itemToValue` props to map custom objects to the required interface. **Example: custom-object** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.items.map((item) => ( {item.flag} {item.country} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    Clear Open
                    {(item) => ( {item.flag} {item.country} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().items as item (item.code)} {item.flag} {item.country} {/each}
                    ``` ### Limit Results Use the `limit` property on `useListCollection` to limit the number of rendered items in the DOM. **Example: limit-results** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    Open
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte City
                    Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ## Guides ### Router Links Customize the `navigate` prop on `Combobox.Root` to integrate with your router. Using Tanstack Router: ```tsx import { Combobox } from '@ark-ui//combobox' import { useNavigate } from '@tanstack/react-router' function Demo() { const navigate = useNavigate() return ( { navigate({ to: e.node.href }) }} > {/* ... */} ) } ``` ### Custom Objects By default, the combobox collection expects an array of objects with `label` and `value` properties. In some cases, you may need to deal with custom objects. Use the `itemToString` and `itemToValue` props to map the custom object to the required interface. ```tsx const items = [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, // ... ] const { collection } = useListCollection({ initialItems: items, itemToString: (item) => item.country, itemToValue: (item) => item.code, }) ``` ### Type Safety The `Combobox.RootComponent` type enables you to create typed wrapper components that maintain full type safety for collection items. ```tsx const Combobox: ArkCombobox.RootComponent = (props) => { return {/* ... */} } ``` Use the wrapper with full type inference on `onValueChange` and other callbacks: ```tsx const App = () => { const { collection } = useListCollection({ initialItems: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, ], }) return ( { // e.items is typed as Array<{ label: string, value: string }> console.log(e.items) }} > {/* ... */} ) } ``` ### Large Datasets The recommended way of managing large lists is to use the `limit` property on the `useListCollection` hook. This will limit the number of rendered items in the DOM to improve performance. ```tsx {3} const { collection } = useListCollection({ initialItems: items, limit: 10, }) ``` ### Available Size The following css variables are exposed to the `Combobox.Positioner` which you can use to style the `Combobox.Content` ```css /* width of the combobox control */ --reference-width: ; /* width of the available viewport */ --available-width: ; /* height of the available viewport */ --available-height: ; ``` For example, if you want to make sure the maximum height doesn't exceed the available height, you can use the following: ```css [data-scope='combobox'][data-part='content'] { max-height: calc(var(--available-height) - 100px); } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether 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. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `collection` | `ListCollection` | No | The collection of items | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item(id: string, index?: number | undefined): string positioner: string itemGroup(id: string | number): string itemGroupLabel(id: string | number): string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `modelValue` | `string[]` | No | The v-model value of the combobox | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ComboboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `MaybeFunction>` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autocomplete' | 'autohighlight'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxItemContext]>` | Yes | | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `{}` | No | | | `persistFocus` | `boolean` | No | | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the combobox is focused | | `open` | `boolean` | Whether the combobox is open | | `inputValue` | `string` | The value of the combobox input | | `highlightedValue` | `string` | The value of the highlighted item | | `highlightedItem` | `V` | The highlighted item | | `setHighlightValue` | `(value: string) => void` | The value of the combobox input | | `clearHighlightValue` | `VoidFunction` | Function to clear the highlighted value | | `syncSelectedItems` | `VoidFunction` | Function to sync the selected items with the value. Useful when `value` is updated from async sources. | | `selectedItems` | `V[]` | The selected items | | `hasSelectedItems` | `boolean` | Whether there's a selected item | | `value` | `string[]` | The selected item keys | | `valueAsString` | `string` | The string representation of the selected items | | `selectValue` | `(value: string) => void` | Function to select a value | | `setValue` | `(value: string[]) => void` | Function to set the value of the combobox | | `clearValue` | `(value?: string) => void` | Function to clear the value of the combobox | | `focus` | `VoidFunction` | Function to focus on the combobox input | | `setInputValue` | `(value: string, reason?: InputValueChangeReason) => void` | Function to set the input value of the combobox | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a combobox item | | `setOpen` | `(open: boolean, reason?: OpenChangeReason) => void` | Function to open or close the combobox | | `collection` | `ListCollection` | Function to toggle the combobox | | `reposition` | `(options?: Partial) => void` | Function to set the positioning options | | `multiple` | `boolean` | Whether the combobox allows multiple selections | | `disabled` | `boolean` | Whether the combobox is disabled | ## Accessibility Complies with the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). ### Keyboard Support **`ArrowDown`** Description: When the combobox is closed, opens the listbox and highlights to the first option. When the combobox is open, moves focus to the next option. **`ArrowUp`** Description: When the combobox is closed, opens the listbox and highlights to the last option. When the combobox is open, moves focus to the previous option. **`Home`** Description: When the combobox is open, moves focus to the first option. **`End`** Description: When the combobox is open, moves focus to the last option. **`Escape`** Description: Closes the listbox. **`Enter`** Description: Selects the highlighted option and closes the combobox. **`Esc`** Description: Closes the combobox # Combobox (SOLID) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Basic = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Basic = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Orange', value: 'orange' }, { label: 'Mango', value: 'mango' }, { label: 'Pineapple', value: 'pineapple' }, { label: 'Strawberry', value: 'strawberry' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Favorite Fruit
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Fruit
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Auto Highlight Automatically highlight the first matching item as the user types by setting `inputBehavior="autohighlight"`. **Example: auto-highlight** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const AutoHighlight = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Engineering', value: 'engineering' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Finance', value: 'finance' }, { label: 'Human Resources', value: 'hr' }, { label: 'Operations', value: 'operations' }, { label: 'Product', value: 'product' }, { label: 'Customer Success', value: 'customer-success' }, { label: 'Legal', value: 'legal' }, { label: 'Information Technology', value: 'information-technology' }, { label: 'Design', value: 'design' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Inline Autocomplete Complete the input value with the first matching item by setting `inputBehavior="autocomplete"`. Use with `startsWith` filter for best results. **Example: inline-autocomplete** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    No results found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const InlineAutocomplete = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Whale', value: 'whale' }, { label: 'Dolphin', value: 'dolphin' }, { label: 'Shark', value: 'shark' }, { label: 'Octopus', value: 'octopus' }, { label: 'Jellyfish', value: 'jellyfish' }, { label: 'Seahorse', value: 'seahorse' }, ], filter: filterFn().startsWith, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Sea Creature
                    Clear Open
                    No results found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Sea Creature
                    Clear Open
                    No results found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Grouping To group related combobox items, use the `groupBy` prop on the collection and `collection.group()` to iterate the groups. **Example: grouping** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Grouping = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.group().map(([continent, group]) => ( {continent} {group.map((item) => ( {item.label} ))} ))}
                    ) } const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Canada', value: 'ca', continent: 'North America' }, { label: 'United States', value: 'us', continent: 'North America' }, { label: 'Mexico', value: 'mx', continent: 'North America' }, { label: 'United Kingdom', value: 'uk', continent: 'Europe' }, { label: 'Germany', value: 'de', continent: 'Europe' }, { label: 'France', value: 'fr', continent: 'Europe' }, { label: 'Japan', value: 'jp', continent: 'Asia' }, { label: 'South Korea', value: 'kr', continent: 'Asia' }, { label: 'China', value: 'cn', continent: 'Asia' }, ] export const Grouping = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, groupBy: (item) => item.continent, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {([continent, group]) => ( {continent} {(item) => ( {item.label} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().group() as [continent, group]} {continent} {#each group as item} {item.label} {/each} {/each}
                    ``` ### Field The `Field` component helps manage form-related state and accessibility attributes of a combobox. It includes handling ARIA labels, helper text, and error text to ensure proper accessibility. **Example: with-field** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Field } from '@ark-ui/react/field' import { useFilter } from '@ark-ui/react/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' export const WithField = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    {collection.items.map((item) => ( {item.label} ))}
                    Select your primary department Department is required
                    ) } const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Field } from '@ark-ui/solid/field' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import styles from 'styles/combobox.module.css' import field from 'styles/field.module.css' const initialItems = [ { label: 'Engineering', value: 'engineering' }, { label: 'Design', value: 'design' }, { label: 'Marketing', value: 'marketing' }, { label: 'Sales', value: 'sales' }, { label: 'Human Resources', value: 'hr' }, { label: 'Finance', value: 'finance' }, ] export const WithField = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Department
                    Clear Open
                    {(item) => ( {item.label} )}
                    Select your primary department Department is required
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Department
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    Select your primary department Department is required
                    ``` ### Context Access the combobox's state with `Combobox.Context` or the `useComboboxContext` hook—useful for displaying the selected value or building custom UI. **Example: context** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Context = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(combobox) =>

                    Selected: {combobox.valueAsString || 'None'}

                    }
                    Size
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Context = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'Small', value: 'sm' }, { label: 'Medium', value: 'md' }, { label: 'Large', value: 'lg' }, { label: 'Extra Large', value: 'xl' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( {(context) =>

                    Selected: {context().valueAsString || 'None'}

                    }
                    Size
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(combobox)}

                    Selected: {combobox().valueAsString || 'None'}

                    {/snippet}
                    Size
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Root Provider An alternative way to control the combobox is to use the `RootProvider` component and the `useCombobox` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const combobox = useCombobox({ collection, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useCombobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'Designer', value: 'designer' }, { label: 'Developer', value: 'developer' }, { label: 'Product Manager', value: 'pm' }, { label: 'Data Scientist', value: 'data-scientist' }, { label: 'DevOps Engineer', value: 'devops' }, { label: 'Marketing Lead', value: 'marketing' }, ] export const RootProvider = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const combobox = useCombobox({ get collection() { return collection() }, onInputValueChange(details) { filter(details.inputValue) }, }) return (
                    Job Title
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte
                    Job Title
                    Clear Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Links Use the `asChild` prop to render the combobox items as links. **Example: links** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const Links = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const initialItems = [ { label: 'GitHub', href: 'https://github.com', value: 'github' }, { label: 'Stack Overflow', href: 'https://stackoverflow.com', value: 'stackoverflow' }, { label: 'MDN Web Docs', href: 'https://developer.mozilla.org', value: 'mdn' }, { label: 'npm', href: 'https://www.npmjs.com', value: 'npm' }, { label: 'TypeScript', href: 'https://www.typescriptlang.org', value: 'typescript' }, { label: 'React', href: 'https://react.dev', value: 'react' }, ] export const Links = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Developer Resources
                    {(item) => ( }> {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Developer Resources
                    Open
                    {#each collection().items as item (item.value)} {#snippet asChild(props)}
                    {item.label} {/snippet} {/each} ``` ### Rehydrate When a combobox has a `defaultValue` or `value` but the `collection` is not loaded yet, you can rehydrate the value to populate the input. **Example: rehydrate-value** #### React ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon } from 'lucide-react' import { useRef, useState } from 'react' import { useAsync } from 'react-use' import styles from 'styles/combobox.module.css' function ComboboxRehydrateValue() { const combobox = useComboboxContext() const hydrated = useRef(false) if (combobox.value.length && combobox.collection.size && !hydrated.current) { combobox.syncSelectedItems() hydrated.current = true } return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = useState('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox({ collection, defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue, onInputValueChange: (e) => setInputValue(e.inputValue), }) const state = useAsync(async () => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue}`) const data = await response.json() set(data.results) }, [inputValue, set]) return ( Search Star Wars Characters {state.loading ? ( Loading... ) : state.error ? ( {state.error.message} ) : ( collection.items.map((item) => ( {item.name} - {item.height}cm / {item.mass}kg )) )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Solid ```tsx import { Combobox, useCombobox, useComboboxContext, useListCollection } from '@ark-ui/solid/combobox' import { For, createEffect, createRenderEffect, createSignal, on } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' import { useAsync } from './use-async' function ComboboxRehydrateValue() { const combobox = useComboboxContext() let hydrated = false createRenderEffect(() => { if (combobox().value.length && combobox().collection.size && !hydrated) { combobox().syncSelectedItems() hydrated = true } }) return null } export const RehydrateValue = () => { const [inputValue, setInputValue] = createSignal('') const { collection, set } = useListCollection({ initialItems: [], itemToString: (item) => item.name, itemToValue: (item) => item.name, }) const combobox = useCombobox(() => ({ collection: collection(), defaultValue: ['C-3PO'], placeholder: 'Example: Dexter', inputValue: inputValue(), onInputValueChange: (e) => setInputValue(e.inputValue), })) const state = useAsync(async (signal) => { const response = await fetch(`https://swapi.py4e.com/api/people/?search=${inputValue()}`, { signal }) const data = await response.json() set(data.results) }) createEffect(on(inputValue, () => state.load())) return ( Search Star Wars Characters {state.loading() ? ( Loading... ) : state.error() ? ( {state.error()?.message} ) : ( {(item) => ( {item.name} - {item.height}cm / {item.mass}kg )} )} ) } interface Character { name: string height: string mass: string created: string edited: string url: string } ``` #### Vue ```vue ``` #### Svelte ```svelte Search Star Wars Characters {#if _state.loading()} Loading... {:else if _state.error()} {_state.error()?.message} {:else} {#each collection().items as item (item.name)} {item.name} - {item.height}cm / {item.mass}kg {/each} {/if} ``` ### Highlight Text Highlight the matching search text in combobox items based on the user's input. **Example: highlight-matching-text** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Highlight } from '@ark-ui/react/highlight' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    {collection.items.map((item) => ( {(context) => } ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { Highlight } from '@ark-ui/solid/highlight' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const HighlightMatchingText = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { label: 'John Smith', value: 'john-smith' }, { label: 'Jane Doe', value: 'jane-doe' }, { label: 'Bob Johnson', value: 'bob-johnson' }, { label: 'Alice Williams', value: 'alice-williams' }, { label: 'Charlie Brown', value: 'charlie-brown' }, { label: 'Diana Ross', value: 'diana-ross' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Assignee
                    Clear Open
                    {(item) => ( {(context) => } )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Assignee
                    Clear Open
                    {#each collection().items as item (item.value)} {#snippet render(context)} {/snippet} {/each}
                    ``` ### Dynamic Generate combobox items dynamically based on user input. This is useful for creating suggestions or autocomplete functionality. **Example: dynamic** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    {collection.items.map((item) => ( {item} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const suggestList = ['gmail.com', 'yahoo.com', 'ark-ui.com'] export const Dynamic = () => { const { collection, set } = useListCollection({ initialItems: [], }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { const items = suggestList.map((item) => `${details.inputValue}@${item}`) set(items) } } return ( Email
                    Open
                    {(item) => ( {item} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Email
                    Open
                    {#each collection().items as item (item)} {item} {/each}
                    ``` ### Creatable Allow users to create new options when their search doesn't match any existing items. This is useful for tags, categories, or other custom values. **Example: creatable** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import { useState } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection.filter((item) => item.toLowerCase() === inputValue.toLowerCase()).size > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = useState([]) const [inputValue, setInputValue] = useState('') const handleInputChange = ({ inputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { flushSync(() => { if (isValidNewOption(inputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(inputValue)) } else if (inputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } }) filter(inputValue) } setInputValue(inputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue)) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue) update(NEW_OPTION_VALUE, getNewOptionData(inputValue)) } } return ( Label
                    {collection.items.map((item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createSignal, For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' interface Item { label: string value: string __new__?: boolean } const NEW_OPTION_VALUE = '[[new]]' const createNewOption = (value: string): Item => ({ label: value, value: NEW_OPTION_VALUE }) const isNewOptionValue = (value: string) => value === NEW_OPTION_VALUE const replaceNewOptionValue = (values: string[], value: string) => values.map((v) => (v === NEW_OPTION_VALUE ? value : v)) const getNewOptionData = (inputValue: string): Item => ({ label: inputValue, value: inputValue, __new__: true }) export const Creatable = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, upsert, update, remove } = useListCollection({ initialItems: [ { label: 'Bug', value: 'bug' }, { label: 'Feature', value: 'feature' }, { label: 'Enhancement', value: 'enhancement' }, { label: 'Documentation', value: 'docs' }, ], filter: filterFn().contains, }) const isValidNewOption = (inputValue: string) => { const exactOptionMatch = collection().items.filter((item) => item.label.toLowerCase() === inputValue.toLowerCase()).length > 0 return !exactOptionMatch && inputValue.trim().length > 0 } const [selectedValue, setSelectedValue] = createSignal([]) const [inputValue, setInputValue] = createSignal('') const handleInputChange = ({ inputValue: newInputValue, reason }: Combobox.InputValueChangeDetails) => { if (reason === 'input-change' || reason === 'item-select') { if (isValidNewOption(newInputValue)) { upsert(NEW_OPTION_VALUE, createNewOption(newInputValue)) } else if (newInputValue.trim().length === 0) { remove(NEW_OPTION_VALUE) } filter(newInputValue) } setInputValue(newInputValue) } const handleOpenChange = ({ reason }: Combobox.OpenChangeDetails) => { if (reason === 'trigger-click') { filter('') } } const handleValueChange = ({ value }: Combobox.ValueChangeDetails) => { setSelectedValue(replaceNewOptionValue(value, inputValue())) if (value.includes(NEW_OPTION_VALUE)) { console.log('New Option Created', inputValue()) update(NEW_OPTION_VALUE, getNewOptionData(inputValue())) } } return ( Label
                    Clear Open
                    {(item) => ( {isNewOptionValue(item.value) ? ( + Create "{item.label}" ) : ( {item.label} {item.__new__ ? '(new)' : ''} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label
                    Clear Open
                    {#each collection().items as item (item.value)} {#if isNewOptionValue(item.value)} + Create "{item.label}" {:else} {item.label} {item.__new__ ? '(new)' : ''} {/if} {/each}
                    ``` ### Multiple Selection Enable multiple selection by setting the `multiple` prop. Selected items can be displayed as tags above the input. **Example: multiple** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import styles from 'styles/combobox.module.css' export const Multiple = () => { const { contains } = useFilter({ sensitivity: 'base' }) const selectedValue = useRef([]) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { selectedValue.current = details.value remove(...details.value) } return ( Skills {(combobox) => (
                    {combobox.selectedItems.length === 0 && None selected} {combobox.selectedItems.map((item: any) => ( {item.label} ))}
                    )}
                    No skills found {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Multiple = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, remove } = useListCollection({ initialItems: [ { label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }, { label: 'Python', value: 'python' }, { label: 'Go', value: 'go' }, { label: 'Rust', value: 'rust' }, { label: 'Java', value: 'java' }, ], filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } const handleValueChange = (details: Combobox.ValueChangeDetails) => { remove(...details.value) } return ( Skills {(context) => (
                    {context().selectedItems.length === 0 && None selected} {(item: any) => {item.label}}
                    )}
                    No skills found {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Skills
                    {#if selectedItems.length === 0} None selected {/if} {#each selectedItems as item (item.value)} {item.label} {/each}
                    Open
                    No skills found {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ### Async Search Load options asynchronously based on user input using the `useAsyncList` hook. This is useful for searching large datasets or fetching data from an API. **Example: async-search** #### React ```tsx import { useAsyncList } from '@ark-ui/react/collection' import { Combobox, createListCollection } from '@ark-ui/react/combobox' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, LoaderIcon, XIcon } from 'lucide-react' import { startTransition } from 'react' import styles from 'styles/combobox.module.css' interface Movie { id: string title: string year: number director: string genre: string } export const AsyncSearch = () => { const list = useAsyncList({ async load({ filterText, signal }) { if (!filterText) return { items: [] } await new Promise((resolve) => setTimeout(resolve, 300)) if (signal?.aborted) return { items: [] } const items = allMovies.filter( (movie) => movie.title.toLowerCase().includes(filterText.toLowerCase()) || movie.director.toLowerCase().includes(filterText.toLowerCase()) || movie.genre.toLowerCase().includes(filterText.toLowerCase()), ) return { items } }, }) const collection = createListCollection({ items: list.items, itemToString: (item) => item.title, itemToValue: (item) => item.id, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { if (details.reason === 'input-change') { startTransition(() => { list.setFilterText(details.inputValue) }) } } return ( Movie
                    {list.loading ? (
                    Searching...
                    ) : list.error ? (
                    {list.error.message}
                    ) : list.items.length === 0 ? (
                    {list.filterText ? 'No results found' : 'Start typing to search movies...'}
                    ) : ( collection.items.map((movie) => ( {movie.title} {movie.year} · {movie.director} )) )}
                    ) } const allMovies: Movie[] = [ { id: 'inception', title: 'Inception', year: 2010, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'the-dark-knight', title: 'The Dark Knight', year: 2008, director: 'Christopher Nolan', genre: 'Action' }, { id: 'pulp-fiction', title: 'Pulp Fiction', year: 1994, director: 'Quentin Tarantino', genre: 'Crime' }, { id: 'the-godfather', title: 'The Godfather', year: 1972, director: 'Francis Ford Coppola', genre: 'Crime' }, { id: 'forrest-gump', title: 'Forrest Gump', year: 1994, director: 'Robert Zemeckis', genre: 'Drama' }, { id: 'the-matrix', title: 'The Matrix', year: 1999, director: 'The Wachowskis', genre: 'Sci-Fi' }, { id: 'interstellar', title: 'Interstellar', year: 2014, director: 'Christopher Nolan', genre: 'Sci-Fi' }, { id: 'parasite', title: 'Parasite', year: 2019, director: 'Bong Joon-ho', genre: 'Thriller' }, { id: 'the-shawshank-redemption', title: 'The Shawshank Redemption', year: 1994, director: 'Frank Darabont', genre: 'Drama', }, { id: 'fight-club', title: 'Fight Club', year: 1999, director: 'David Fincher', genre: 'Drama' }, { id: 'goodfellas', title: 'Goodfellas', year: 1990, director: 'Martin Scorsese', genre: 'Crime' }, { id: 'the-silence-of-the-lambs', title: 'The Silence of the Lambs', year: 1991, director: 'Jonathan Demme', genre: 'Thriller', }, ] ``` ### Virtualized For very large lists, use virtualization with `@tanstack/virtual` to render only the visible items. Pass the `scrollToIndexFn` prop to enable keyboard navigation within the virtualized list. **Example: virtualized** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { useVirtualizer } from '@tanstack/react-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import { useRef } from 'react' import { flushSync } from 'react-dom' import styles from 'styles/combobox.module.css' export const Virtualized = () => { const contentRef = useRef(null) const { startsWith } = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: startsWith, }) const virtualizer = useVirtualizer({ count: collection.size, getScrollElement: () => contentRef.current, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { flushSync(() => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection.items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { createVirtualizer } from '@tanstack/solid-virtual' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-solid' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const Virtualized = () => { let contentRef: HTMLDivElement | undefined const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter, reset } = useListCollection({ initialItems: countries, filter: filterFn().startsWith, }) const virtualizer = createVirtualizer({ get count() { return collection().size }, getScrollElement: () => contentRef ?? null, estimateSize: () => 32, overscan: 10, }) const handleScrollToIndex: Combobox.RootProps['scrollToIndexFn'] = (details) => { virtualizer.scrollToIndex(details.index, { align: 'center', behavior: 'auto', }) } const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {virtualizer.getVirtualItems().map((virtualItem) => { const item = collection().items[virtualItem.index] return ( {item.emoji} {item.label} ) })}
                    ) } interface Country { value: string label: string emoji: string } const countries: Country[] = [ { value: 'AD', label: 'Andorra', emoji: '🇦🇩' }, { value: 'AE', label: 'United Arab Emirates', emoji: '🇦🇪' }, { value: 'AF', label: 'Afghanistan', emoji: '🇦🇫' }, { value: 'AG', label: 'Antigua and Barbuda', emoji: '🇦🇬' }, { value: 'AI', label: 'Anguilla', emoji: '🇦🇮' }, { value: 'AL', label: 'Albania', emoji: '🇦🇱' }, { value: 'AM', label: 'Armenia', emoji: '🇦🇲' }, { value: 'AO', label: 'Angola', emoji: '🇦🇴' }, { value: 'AQ', label: 'Antarctica', emoji: '🇦🇶' }, { value: 'AR', label: 'Argentina', emoji: '🇦🇷' }, { value: 'AS', label: 'American Samoa', emoji: '🇦🇸' }, { value: 'AT', label: 'Austria', emoji: '🇦🇹' }, { value: 'AU', label: 'Australia', emoji: '🇦🇺' }, { value: 'AW', label: 'Aruba', emoji: '🇦🇼' }, { value: 'AX', label: 'Åland Islands', emoji: '🇦🇽' }, { value: 'AZ', label: 'Azerbaijan', emoji: '🇦🇿' }, { value: 'BA', label: 'Bosnia and Herzegovina', emoji: '🇧🇦' }, { value: 'BB', label: 'Barbados', emoji: '🇧🇧' }, { value: 'BD', label: 'Bangladesh', emoji: '🇧🇩' }, { value: 'BE', label: 'Belgium', emoji: '🇧🇪' }, { value: 'BF', label: 'Burkina Faso', emoji: '🇧🇫' }, { value: 'BG', label: 'Bulgaria', emoji: '🇧🇬' }, { value: 'BH', label: 'Bahrain', emoji: '🇧🇭' }, { value: 'BI', label: 'Burundi', emoji: '🇧🇮' }, { value: 'BJ', label: 'Benin', emoji: '🇧🇯' }, { value: 'BL', label: 'Saint Barthélemy', emoji: '🇧🇱' }, { value: 'BM', label: 'Bermuda', emoji: '🇧🇲' }, { value: 'BN', label: 'Brunei', emoji: '🇧🇳' }, { value: 'BO', label: 'Bolivia', emoji: '🇧🇴' }, { value: 'BR', label: 'Brazil', emoji: '🇧🇷' }, { value: 'BS', label: 'Bahamas', emoji: '🇧🇸' }, { value: 'BT', label: 'Bhutan', emoji: '🇧🇹' }, { value: 'BW', label: 'Botswana', emoji: '🇧🇼' }, { value: 'BY', label: 'Belarus', emoji: '🇧🇾' }, { value: 'BZ', label: 'Belize', emoji: '🇧🇿' }, { value: 'CA', label: 'Canada', emoji: '🇨🇦' }, { value: 'CD', label: 'Congo', emoji: '🇨🇩' }, { value: 'CF', label: 'Central African Republic', emoji: '🇨🇫' }, { value: 'CH', label: 'Switzerland', emoji: '🇨🇭' }, { value: 'CI', label: "Côte d'Ivoire", emoji: '🇨🇮' }, { value: 'CK', label: 'Cook Islands', emoji: '🇨🇰' }, { value: 'CL', label: 'Chile', emoji: '🇨🇱' }, { value: 'CM', label: 'Cameroon', emoji: '🇨🇲' }, { value: 'CN', label: 'China', emoji: '🇨🇳' }, { value: 'CO', label: 'Colombia', emoji: '🇨🇴' }, { value: 'CR', label: 'Costa Rica', emoji: '🇨🇷' }, { value: 'CU', label: 'Cuba', emoji: '🇨🇺' }, { value: 'CV', label: 'Cabo Verde', emoji: '🇨🇻' }, { value: 'CY', label: 'Cyprus', emoji: '🇨🇾' }, { value: 'CZ', label: 'Czech Republic', emoji: '🇨🇿' }, { value: 'DE', label: 'Germany', emoji: '🇩🇪' }, { value: 'DJ', label: 'Djibouti', emoji: '🇩🇯' }, { value: 'DK', label: 'Denmark', emoji: '🇩🇰' }, { value: 'DM', label: 'Dominica', emoji: '🇩🇲' }, { value: 'DO', label: 'Dominican Republic', emoji: '🇩🇴' }, { value: 'DZ', label: 'Algeria', emoji: '🇩🇿' }, { value: 'EC', label: 'Ecuador', emoji: '🇪🇨' }, { value: 'EE', label: 'Estonia', emoji: '🇪🇪' }, { value: 'EG', label: 'Egypt', emoji: '🇪🇬' }, { value: 'ER', label: 'Eritrea', emoji: '🇪🇷' }, { value: 'ES', label: 'Spain', emoji: '🇪🇸' }, { value: 'ET', label: 'Ethiopia', emoji: '🇪🇹' }, { value: 'FI', label: 'Finland', emoji: '🇫🇮' }, { value: 'FJ', label: 'Fiji', emoji: '🇫🇯' }, { value: 'FK', label: 'Falkland Islands', emoji: '🇫🇰' }, { value: 'FM', label: 'Micronesia', emoji: '🇫🇲' }, { value: 'FO', label: 'Faroe Islands', emoji: '🇫🇴' }, { value: 'FR', label: 'France', emoji: '🇫🇷' }, { value: 'GA', label: 'Gabon', emoji: '🇬🇦' }, { value: 'GB', label: 'United Kingdom', emoji: '🇬🇧' }, { value: 'GD', label: 'Grenada', emoji: '🇬🇩' }, { value: 'GE', label: 'Georgia', emoji: '🇬🇪' }, { value: 'GH', label: 'Ghana', emoji: '🇬🇭' }, { value: 'GI', label: 'Gibraltar', emoji: '🇬🇮' }, { value: 'GL', label: 'Greenland', emoji: '🇬🇱' }, { value: 'GM', label: 'Gambia', emoji: '🇬🇲' }, { value: 'GN', label: 'Guinea', emoji: '🇬🇳' }, { value: 'GQ', label: 'Equatorial Guinea', emoji: '🇬🇶' }, { value: 'GR', label: 'Greece', emoji: '🇬🇷' }, { value: 'GT', label: 'Guatemala', emoji: '🇬🇹' }, { value: 'GU', label: 'Guam', emoji: '🇬🇺' }, { value: 'GW', label: 'Guinea-Bissau', emoji: '🇬🇼' }, { value: 'GY', label: 'Guyana', emoji: '🇬🇾' }, { value: 'HK', label: 'Hong Kong', emoji: '🇭🇰' }, { value: 'HN', label: 'Honduras', emoji: '🇭🇳' }, { value: 'HR', label: 'Croatia', emoji: '🇭🇷' }, { value: 'HT', label: 'Haiti', emoji: '🇭🇹' }, { value: 'HU', label: 'Hungary', emoji: '🇭🇺' }, { value: 'ID', label: 'Indonesia', emoji: '🇮🇩' }, { value: 'IE', label: 'Ireland', emoji: '🇮🇪' }, { value: 'IL', label: 'Israel', emoji: '🇮🇱' }, { value: 'IM', label: 'Isle of Man', emoji: '🇮🇲' }, { value: 'IN', label: 'India', emoji: '🇮🇳' }, { value: 'IQ', label: 'Iraq', emoji: '🇮🇶' }, { value: 'IR', label: 'Iran', emoji: '🇮🇷' }, { value: 'IS', label: 'Iceland', emoji: '🇮🇸' }, { value: 'IT', label: 'Italy', emoji: '🇮🇹' }, { value: 'JE', label: 'Jersey', emoji: '🇯🇪' }, { value: 'JM', label: 'Jamaica', emoji: '🇯🇲' }, { value: 'JO', label: 'Jordan', emoji: '🇯🇴' }, { value: 'JP', label: 'Japan', emoji: '🇯🇵' }, { value: 'KE', label: 'Kenya', emoji: '🇰🇪' }, { value: 'KG', label: 'Kyrgyzstan', emoji: '🇰🇬' }, { value: 'KH', label: 'Cambodia', emoji: '🇰🇭' }, { value: 'KI', label: 'Kiribati', emoji: '🇰🇮' }, { value: 'KM', label: 'Comoros', emoji: '🇰🇲' }, { value: 'KN', label: 'Saint Kitts and Nevis', emoji: '🇰🇳' }, { value: 'KP', label: 'North Korea', emoji: '🇰🇵' }, { value: 'KR', label: 'South Korea', emoji: '🇰🇷' }, { value: 'KW', label: 'Kuwait', emoji: '🇰🇼' }, { value: 'KY', label: 'Cayman Islands', emoji: '🇰🇾' }, { value: 'KZ', label: 'Kazakhstan', emoji: '🇰🇿' }, { value: 'LA', label: 'Laos', emoji: '🇱🇦' }, { value: 'LB', label: 'Lebanon', emoji: '🇱🇧' }, { value: 'LC', label: 'Saint Lucia', emoji: '🇱🇨' }, { value: 'LI', label: 'Liechtenstein', emoji: '🇱🇮' }, { value: 'LK', label: 'Sri Lanka', emoji: '🇱🇰' }, { value: 'LR', label: 'Liberia', emoji: '🇱🇷' }, { value: 'LS', label: 'Lesotho', emoji: '🇱🇸' }, { value: 'LT', label: 'Lithuania', emoji: '🇱🇹' }, { value: 'LU', label: 'Luxembourg', emoji: '🇱🇺' }, { value: 'LV', label: 'Latvia', emoji: '🇱🇻' }, { value: 'LY', label: 'Libya', emoji: '🇱🇾' }, { value: 'MA', label: 'Morocco', emoji: '🇲🇦' }, { value: 'MC', label: 'Monaco', emoji: '🇲🇨' }, { value: 'MD', label: 'Moldova', emoji: '🇲🇩' }, { value: 'ME', label: 'Montenegro', emoji: '🇲🇪' }, { value: 'MG', label: 'Madagascar', emoji: '🇲🇬' }, { value: 'MH', label: 'Marshall Islands', emoji: '🇲🇭' }, { value: 'MK', label: 'North Macedonia', emoji: '🇲🇰' }, { value: 'ML', label: 'Mali', emoji: '🇲🇱' }, { value: 'MM', label: 'Myanmar', emoji: '🇲🇲' }, { value: 'MN', label: 'Mongolia', emoji: '🇲🇳' }, { value: 'MO', label: 'Macao', emoji: '🇲🇴' }, { value: 'MR', label: 'Mauritania', emoji: '🇲🇷' }, { value: 'MS', label: 'Montserrat', emoji: '🇲🇸' }, { value: 'MT', label: 'Malta', emoji: '🇲🇹' }, { value: 'MU', label: 'Mauritius', emoji: '🇲🇺' }, { value: 'MV', label: 'Maldives', emoji: '🇲🇻' }, { value: 'MW', label: 'Malawi', emoji: '🇲🇼' }, { value: 'MX', label: 'Mexico', emoji: '🇲🇽' }, { value: 'MY', label: 'Malaysia', emoji: '🇲🇾' }, { value: 'MZ', label: 'Mozambique', emoji: '🇲🇿' }, { value: 'NA', label: 'Namibia', emoji: '🇳🇦' }, { value: 'NC', label: 'New Caledonia', emoji: '🇳🇨' }, { value: 'NE', label: 'Niger', emoji: '🇳🇪' }, { value: 'NF', label: 'Norfolk Island', emoji: '🇳🇫' }, { value: 'NG', label: 'Nigeria', emoji: '🇳🇬' }, { value: 'NI', label: 'Nicaragua', emoji: '🇳🇮' }, { value: 'NL', label: 'Netherlands', emoji: '🇳🇱' }, { value: 'NO', label: 'Norway', emoji: '🇳🇴' }, { value: 'NP', label: 'Nepal', emoji: '🇳🇵' }, { value: 'NR', label: 'Nauru', emoji: '🇳🇷' }, { value: 'NU', label: 'Niue', emoji: '🇳🇺' }, { value: 'NZ', label: 'New Zealand', emoji: '🇳🇿' }, { value: 'OM', label: 'Oman', emoji: '🇴🇲' }, { value: 'PA', label: 'Panama', emoji: '🇵🇦' }, { value: 'PE', label: 'Peru', emoji: '🇵🇪' }, { value: 'PF', label: 'French Polynesia', emoji: '🇵🇫' }, { value: 'PG', label: 'Papua New Guinea', emoji: '🇵🇬' }, { value: 'PH', label: 'Philippines', emoji: '🇵🇭' }, { value: 'PK', label: 'Pakistan', emoji: '🇵🇰' }, { value: 'PL', label: 'Poland', emoji: '🇵🇱' }, { value: 'PR', label: 'Puerto Rico', emoji: '🇵🇷' }, { value: 'PS', label: 'Palestine', emoji: '🇵🇸' }, { value: 'PT', label: 'Portugal', emoji: '🇵🇹' }, { value: 'PW', label: 'Palau', emoji: '🇵🇼' }, { value: 'PY', label: 'Paraguay', emoji: '🇵🇾' }, { value: 'QA', label: 'Qatar', emoji: '🇶🇦' }, { value: 'RO', label: 'Romania', emoji: '🇷🇴' }, { value: 'RS', label: 'Serbia', emoji: '🇷🇸' }, { value: 'RU', label: 'Russia', emoji: '🇷🇺' }, { value: 'RW', label: 'Rwanda', emoji: '🇷🇼' }, { value: 'SA', label: 'Saudi Arabia', emoji: '🇸🇦' }, { value: 'SB', label: 'Solomon Islands', emoji: '🇸🇧' }, { value: 'SC', label: 'Seychelles', emoji: '🇸🇨' }, { value: 'SD', label: 'Sudan', emoji: '🇸🇩' }, { value: 'SE', label: 'Sweden', emoji: '🇸🇪' }, { value: 'SG', label: 'Singapore', emoji: '🇸🇬' }, { value: 'SI', label: 'Slovenia', emoji: '🇸🇮' }, { value: 'SK', label: 'Slovakia', emoji: '🇸🇰' }, { value: 'SL', label: 'Sierra Leone', emoji: '🇸🇱' }, { value: 'SM', label: 'San Marino', emoji: '🇸🇲' }, { value: 'SN', label: 'Senegal', emoji: '🇸🇳' }, { value: 'SO', label: 'Somalia', emoji: '🇸🇴' }, { value: 'SR', label: 'Suriname', emoji: '🇸🇷' }, { value: 'SS', label: 'South Sudan', emoji: '🇸🇸' }, { value: 'ST', label: 'Sao Tome and Principe', emoji: '🇸🇹' }, { value: 'SV', label: 'El Salvador', emoji: '🇸🇻' }, { value: 'SY', label: 'Syria', emoji: '🇸🇾' }, { value: 'SZ', label: 'Eswatini', emoji: '🇸🇿' }, { value: 'TC', label: 'Turks and Caicos Islands', emoji: '🇹🇨' }, { value: 'TD', label: 'Chad', emoji: '🇹🇩' }, { value: 'TG', label: 'Togo', emoji: '🇹🇬' }, { value: 'TH', label: 'Thailand', emoji: '🇹🇭' }, { value: 'TJ', label: 'Tajikistan', emoji: '🇹🇯' }, { value: 'TK', label: 'Tokelau', emoji: '🇹🇰' }, { value: 'TL', label: 'Timor-Leste', emoji: '🇹🇱' }, { value: 'TM', label: 'Turkmenistan', emoji: '🇹🇲' }, { value: 'TN', label: 'Tunisia', emoji: '🇹🇳' }, { value: 'TO', label: 'Tonga', emoji: '🇹🇴' }, { value: 'TR', label: 'Türkiye', emoji: '🇹🇷' }, { value: 'TT', label: 'Trinidad and Tobago', emoji: '🇹🇹' }, { value: 'TV', label: 'Tuvalu', emoji: '🇹🇻' }, { value: 'TW', label: 'Taiwan', emoji: '🇹🇼' }, { value: 'TZ', label: 'Tanzania', emoji: '🇹🇿' }, { value: 'UA', label: 'Ukraine', emoji: '🇺🇦' }, { value: 'UG', label: 'Uganda', emoji: '🇺🇬' }, { value: 'US', label: 'United States', emoji: '🇺🇸' }, { value: 'UY', label: 'Uruguay', emoji: '🇺🇾' }, { value: 'UZ', label: 'Uzbekistan', emoji: '🇺🇿' }, { value: 'VA', label: 'Vatican City', emoji: '🇻🇦' }, { value: 'VC', label: 'Saint Vincent and the Grenadines', emoji: '🇻🇨' }, { value: 'VE', label: 'Venezuela', emoji: '🇻🇪' }, { value: 'VG', label: 'British Virgin Islands', emoji: '🇻🇬' }, { value: 'VI', label: 'U.S. Virgin Islands', emoji: '🇻🇮' }, { value: 'VN', label: 'Vietnam', emoji: '🇻🇳' }, { value: 'VU', label: 'Vanuatu', emoji: '🇻🇺' }, { value: 'WF', label: 'Wallis and Futuna', emoji: '🇼🇫' }, { value: 'WS', label: 'Samoa', emoji: '🇼🇸' }, { value: 'YE', label: 'Yemen', emoji: '🇾🇪' }, { value: 'YT', label: 'Mayotte', emoji: '🇾🇹' }, { value: 'ZA', label: 'South Africa', emoji: '🇿🇦' }, { value: 'ZM', label: 'Zambia', emoji: '🇿🇲' }, { value: 'ZW', label: 'Zimbabwe', emoji: '🇿🇼' }, ] ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Open
                    {#each $virtualizer.getVirtualItems() as virtualItem (virtualItem.key)} {@const item = collection().items[virtualItem.index]} {item.label} {/each}
                    ``` ### Custom Object Use the `itemToString` and `itemToValue` props to map custom objects to the required interface. **Example: custom-object** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon, XIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    {collection.items.map((item) => ( {item.flag} {item.country} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' export const CustomObject = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, ], itemToString: (item) => item.country, itemToValue: (item) => item.code, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( Country
                    Clear Open
                    {(item) => ( {item.flag} {item.country} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Country
                    Clear Open
                    {#each collection().items as item (item.code)} {item.flag} {item.country} {/each}
                    ``` ### Limit Results Use the `limit` property on `useListCollection` to limit the number of rendered items in the DOM. **Example: limit-results** #### React ```tsx import { Combobox, useListCollection } from '@ark-ui/react/combobox' import { useFilter } from '@ark-ui/react/locale' import { Portal } from '@ark-ui/react/portal' import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const { contains } = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    {collection.items.map((item) => ( {item.label} ))}
                    ) } ``` #### Solid ```tsx import { Combobox, useListCollection } from '@ark-ui/solid/combobox' import { useFilter } from '@ark-ui/solid/locale' import { For } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/combobox.module.css' const cities = [ { label: 'New York', value: 'new-york' }, { label: 'Los Angeles', value: 'los-angeles' }, { label: 'Chicago', value: 'chicago' }, { label: 'Houston', value: 'houston' }, { label: 'Phoenix', value: 'phoenix' }, { label: 'Philadelphia', value: 'philadelphia' }, { label: 'San Antonio', value: 'san-antonio' }, { label: 'San Diego', value: 'san-diego' }, { label: 'Dallas', value: 'dallas' }, { label: 'San Jose', value: 'san-jose' }, { label: 'Austin', value: 'austin' }, { label: 'Jacksonville', value: 'jacksonville' }, { label: 'Fort Worth', value: 'fort-worth' }, { label: 'Columbus', value: 'columbus' }, { label: 'Charlotte', value: 'charlotte' }, { label: 'San Francisco', value: 'san-francisco' }, { label: 'Indianapolis', value: 'indianapolis' }, { label: 'Seattle', value: 'seattle' }, { label: 'Denver', value: 'denver' }, { label: 'Boston', value: 'boston' }, ] export const LimitResults = () => { const filterFn = useFilter({ sensitivity: 'base' }) const { collection, filter } = useListCollection({ initialItems: cities, limit: 5, filter: filterFn().contains, }) const handleInputChange = (details: Combobox.InputValueChangeDetails) => { filter(details.inputValue) } return ( City
                    Open
                    {(item) => ( {item.label} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte City
                    Open
                    {#each collection().items as item (item.value)} {item.label} {/each}
                    ``` ## Guides ### Router Links Customize the `navigate` prop on `Combobox.Root` to integrate with your router. Using Tanstack Router: ```tsx import { Combobox } from '@ark-ui//combobox' import { useNavigate } from '@tanstack/react-router' function Demo() { const navigate = useNavigate() return ( { navigate({ to: e.node.href }) }} > {/* ... */} ) } ``` ### Custom Objects By default, the combobox collection expects an array of objects with `label` and `value` properties. In some cases, you may need to deal with custom objects. Use the `itemToString` and `itemToValue` props to map the custom object to the required interface. ```tsx const items = [ { country: 'United States', code: 'US', flag: '🇺🇸' }, { country: 'Canada', code: 'CA', flag: '🇨🇦' }, { country: 'Australia', code: 'AU', flag: '🇦🇺' }, // ... ] const { collection } = useListCollection({ initialItems: items, itemToString: (item) => item.country, itemToValue: (item) => item.code, }) ``` ### Type Safety The `Combobox.RootComponent` type enables you to create typed wrapper components that maintain full type safety for collection items. ```tsx const Combobox: ArkCombobox.RootComponent = (props) => { return {/* ... */} } ``` Use the wrapper with full type inference on `onValueChange` and other callbacks: ```tsx const App = () => { const { collection } = useListCollection({ initialItems: [ { label: 'React', value: 'react' }, { label: 'Vue', value: 'vue' }, ], }) return ( { // e.items is typed as Array<{ label: string, value: string }> console.log(e.items) }} > {/* ... */} ) } ``` ### Large Datasets The recommended way of managing large lists is to use the `limit` property on the `useListCollection` hook. This will limit the number of rendered items in the DOM to improve performance. ```tsx {3} const { collection } = useListCollection({ initialItems: items, limit: 10, }) ``` ### Available Size The following css variables are exposed to the `Combobox.Positioner` which you can use to style the `Combobox.Content` ```css /* width of the combobox control */ --reference-width: ; /* width of the available viewport */ --available-width: ; /* height of the available viewport */ --available-height: ; ``` For example, if you want to make sure the maximum height doesn't exceed the available height, you can use the following: ```css [data-scope='combobox'][data-part='content'] { max-height: calc(var(--available-height) - 100px); } ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `ListCollection` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'span'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether 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. | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `collection` | `ListCollection` | No | The collection of items | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item(id: string, index?: number | undefined): string positioner: string itemGroup(id: string | number): string itemGroupLabel(id: string | number): string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `inputBehavior` | `'none' | 'autohighlight' | 'autocomplete'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `modelValue` | `string[]` | No | The v-model value of the combobox | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'clear' | 'replace' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `any` | No | The item to render | | `persistFocus` | `boolean` | No | Whether hovering outside should clear the highlighted state | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `ComboboxApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `focusable` | `boolean` | No | Whether the trigger is focusable | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `collection` | `MaybeFunction>` | Yes | The collection of items | | `allowCustomValue` | `boolean` | No | Whether to allow typing custom values in the input | | `alwaysSubmitOnEnter` | `boolean` | No | Whether to always submit on Enter key press, even if popup is open. Useful for single-field autocomplete forms where Enter should submit the form. | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `autoFocus` | `boolean` | No | Whether to autofocus the input on mount | | `closeOnSelect` | `boolean` | No | Whether to close the combobox when an item is selected. | | `composite` | `boolean` | No | Whether the combobox is a composed with other composite widgets like tabs | | `defaultHighlightedValue` | `string` | No | The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. | | `defaultInputValue` | `string` | No | The initial value of the combobox's input when rendered. Use when you don't need to control the value of the combobox's input. | | `defaultOpen` | `boolean` | No | The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. | | `defaultValue` | `string[]` | No | The initial value of the combobox's selected items when rendered. Use when you don't need to control the value of the combobox's selected items. | | `disabled` | `boolean` | No | Whether the combobox is disabled | | `disableLayer` | `boolean` | No | Whether to disable registering this a dismissable layer | | `form` | `string` | No | The associate form of the combobox. | | `highlightedValue` | `string` | No | The controlled highlighted value of the combobox | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string label: string control: string input: string content: string trigger: string clearTrigger: string item: (id: string, index?: number | undefined) => string positioner: string itemGroup: (id: string | number) => string itemGroupLabel: (id: string | number) => string }>` | No | The ids of the elements in the combobox. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inputBehavior` | `'none' | 'autocomplete' | 'autohighlight'` | No | Defines the auto-completion behavior of the combobox. - `autohighlight`: The first focused item is highlighted as the user types - `autocomplete`: Navigating the listbox with the arrow keys selects the item and the input is updated | | `inputValue` | `string` | No | The controlled value of the combobox's input | | `invalid` | `boolean` | No | Whether the combobox is invalid | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation through the items | | `multiple` | `boolean` | No | Whether to allow multiple selection. **Good to know:** When `multiple` is `true`, the `selectionBehavior` is automatically set to `clear`. It is recommended to render the selected items in a separate container. | | `name` | `string` | No | The `name` attribute of the combobox's input. Useful for form submission | | `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component | | `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when an item is highlighted using the pointer or keyboard navigation. | | `onInputValueChange` | `(details: InputValueChangeDetails) => void` | No | Function called when the input's value changes | | `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the popup is opened | | `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component | | `onSelect` | `(details: SelectionDetails) => void` | No | Function called when an item is selected | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when a new item is selected | | `open` | `boolean` | No | The controlled open state of the combobox | | `openOnChange` | `boolean | ((details: InputValueChangeDetails) => boolean)` | No | Whether to show the combobox when the input value changes | | `openOnClick` | `boolean` | No | Whether to open the combobox popup on initial click on the input | | `openOnKeyPress` | `boolean` | No | Whether to open the combobox on arrow key press | | `placeholder` | `string` | No | The placeholder text of the combobox's input | | `positioning` | `PositioningOptions` | No | The positioning options to dynamically position the menu | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it | | `ref` | `Element` | No | | | `required` | `boolean` | No | Whether the combobox is required | | `scrollToIndexFn` | `(details: ScrollToIndexDetails) => void` | No | Function to scroll to a specific index | | `selectionBehavior` | `'replace' | 'clear' | 'preserve'` | No | The behavior of the combobox input when an item is selected - `replace`: The selected item string is set as the input value - `clear`: The input value is cleared - `preserve`: The input value is preserved | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `string[]` | No | The controlled value of the combobox's selected items | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | root | | `[data-invalid]` | Present when invalid | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ClearTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | clear-trigger | | `[data-invalid]` | Present when invalid | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | listbox | | `[data-has-nested]` | listbox | | `[data-placement]` | The placement of the content | | `[data-empty]` | Present when the content is empty | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested comboboxs | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | control | | `[data-state]` | "open" | "closed" | | `[data-focus]` | Present when focused | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | **Empty Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | input | | `[data-invalid]` | Present when invalid | | `[data-autofocus]` | | | `[data-state]` | "open" | "closed" | **ItemContext Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseComboboxItemContext]>` | Yes | | **ItemGroupLabel Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemGroup Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `id` | `string` | No | | | `ref` | `Element` | No | | **ItemGroup Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-group | | `[data-empty]` | Present when the content is empty | **ItemIndicator Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemIndicator Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-indicator | | `[data-state]` | "checked" | "unchecked" | **Item Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `item` | `{}` | No | | | `persistFocus` | `boolean` | No | | | `ref` | `Element` | No | | **Item Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item | | `[data-highlighted]` | Present when highlighted | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-value]` | The value of the item | **ItemText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ItemText Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | item-text | | `[data-state]` | "checked" | "unchecked" | | `[data-disabled]` | Present when disabled | | `[data-highlighted]` | Present when highlighted | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | label | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | | `[data-invalid]` | Present when invalid | | `[data-required]` | Present when required | | `[data-focus]` | Present when focused | **List Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **List Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | list | | `[data-empty]` | Present when the content is empty | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseComboboxReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `ref` | `Element` | No | | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | combobox | | `[data-part]` | trigger | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | | `[data-focusable]` | | | `[data-readonly]` | Present when read-only | | `[data-disabled]` | Present when disabled | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the combobox is focused | | `open` | `boolean` | Whether the combobox is open | | `inputValue` | `string` | The value of the combobox input | | `highlightedValue` | `string` | The value of the highlighted item | | `highlightedItem` | `V` | The highlighted item | | `setHighlightValue` | `(value: string) => void` | The value of the combobox input | | `clearHighlightValue` | `VoidFunction` | Function to clear the highlighted value | | `syncSelectedItems` | `VoidFunction` | Function to sync the selected items with the value. Useful when `value` is updated from async sources. | | `selectedItems` | `V[]` | The selected items | | `hasSelectedItems` | `boolean` | Whether there's a selected item | | `value` | `string[]` | The selected item keys | | `valueAsString` | `string` | The string representation of the selected items | | `selectValue` | `(value: string) => void` | Function to select a value | | `setValue` | `(value: string[]) => void` | Function to set the value of the combobox | | `clearValue` | `(value?: string) => void` | Function to clear the value of the combobox | | `focus` | `VoidFunction` | Function to focus on the combobox input | | `setInputValue` | `(value: string, reason?: InputValueChangeReason) => void` | Function to set the input value of the combobox | | `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of a combobox item | | `setOpen` | `(open: boolean, reason?: OpenChangeReason) => void` | Function to open or close the combobox | | `collection` | `ListCollection` | Function to toggle the combobox | | `reposition` | `(options?: Partial) => void` | Function to set the positioning options | | `multiple` | `boolean` | Whether the combobox allows multiple selections | | `disabled` | `boolean` | Whether the combobox is disabled | ## Accessibility Complies with the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). ### Keyboard Support **`ArrowDown`** Description: When the combobox is closed, opens the listbox and highlights to the first option. When the combobox is open, moves focus to the next option. **`ArrowUp`** Description: When the combobox is closed, opens the listbox and highlights to the last option. When the combobox is open, moves focus to the previous option. **`Home`** Description: When the combobox is open, moves focus to the first option. **`End`** Description: When the combobox is open, moves focus to the last option. **`Escape`** Description: Closes the listbox. **`Enter`** Description: Selects the highlighted option and closes the combobox. **`Esc`** Description: Closes the combobox # Date Picker (REACT) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Default Value Use the `defaultValue` prop with `parseDate` to set the initial date value. **Example: default-value** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Controlled Use the `value` and `onValueChange` props to control the date picker's value programmatically. **Example: controlled** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = useState([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = createSignal([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Root Provider An alternative way to control the date picker is to use the `RootProvider` component and the `useDatePicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { DatePicker, useDatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RootProvider = () => { const datePicker = useDatePicker() return (
                    Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker, useDatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RootProvider = () => { const datePicker = useDatePicker() return ( <> Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Default View Use the `defaultView` prop to set which view (day, month, or year) the calendar opens to initially. **Example: default-view** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultView = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultView = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Month and Year Select Use `MonthSelect` and `YearSelect` components to create a header with dropdown selects for quick month/year navigation, alongside the prev/next triggers. **Example: month-year-select** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import styles from 'styles/date-picker.module.css' export const MonthYearSelect = () => { return ( Label {(datePicker) => ( <>
                    {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/date-picker.module.css' export const MonthYearSelect = () => { return ( Label {(context) => ( <>
                    {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label {#snippet render(datePicker)}
                    {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet}
                    ``` ### Range To create a date picker that allows a range selection, you need to: - Set the `selectionMode` prop to `range`. - Render multiple inputs with the `index` prop set to `0` and `1`. **Example: range-selection** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RangeSelection = () => { return ( Label Clear Last 7 days {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon } from 'lucide-solid' import { Index, createMemo } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RangeSelection = () => { return ( Label Clear Last 7 days
                    {(context) => ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => { const offset = createMemo(() => context().getOffset({ months: 1 })) return ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} ) }}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear Last 7 days {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Multiple Use the `selectionMode="multiple"` prop to allow selecting multiple dates. This example also shows how to display selected dates as removable tags. **Example: multi-selection** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatWithDay = (date: DateValue) => { const jsDate = date.toDate('UTC') return jsDate.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', }) } export const MultiSelection = () => { return ( Label {(datePicker) => (
                    {datePicker.value.length === 0 ? ( Select dates... ) : ( datePicker.value.map((date, index) => ( {formatWithDay(date)} )) )}
                    )}
                    Clear
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { For, Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultiSelection = () => { return ( Label {(context) => (
                    {context().value.length === 0 ? ( Select dates... ) : ( {(date, index) => ( {date.toDate('UTC').toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', })} )} )}
                    )}
                    Clear
                    {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Multiple Months To create a date picker that displays multiple months side by side: - Set the `numOfMonths` prop to the number of months you want to display. - Use the `datePicker.getOffset({ months: 1 })` to get data for the next month. **Example: multiple-months** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultipleMonths = () => { return ( Label Clear
                    {(datePicker) => ( {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => { const offset = datePicker.getOffset({ months: 1 }) return ( {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {offset.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} ) }}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createMemo } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultipleMonths = () => { return ( Label Clear
                    {(datePicker) => ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(datePicker) => { const offset = createMemo(() => datePicker().getOffset({ months: 1 })) return ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} ) }}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear
                    {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay, id (id)} {weekDay.short} {/each} {#each datePicker().weeks as week, id} {#each week as day, id (id)} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {@const offset = datePicker().getOffset({ months: 1 })} {#each datePicker().weekDays as weekDay, id (id)} {weekDay.short} {/each} {#each offset.weeks as week, id (id)} {#each week as day, id (id)} {day.day} {/each} {/each} {/snippet}
                    ``` ### Presets Use the `DatePicker.PresetTrigger` component to add quick-select preset options like "Last 7 days" or "This month". **Example: presets** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Presets = () => { return ( Label Clear
                    Last 7 days Last 30 days This month Last month
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Presets = () => { return ( Label Clear
                    Last 7 days Last 30 days This month
                    {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear
                    Last 7 days Last 30 days This month
                    {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet}
                    ``` ### Min and Max Use the `min` and `max` props with `parseDate` to restrict the selectable date range. Dates outside this range will be disabled. **Example: min-max** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MinMax = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MinMax = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Unavailable Use the `isDateUnavailable` prop to mark specific dates as unavailable. This example disables weekends. **Example: unavailable** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const isWeekend = (date: DateValue) => { const dayOfWeek = date.toDate('UTC').getDay() return dayOfWeek === 0 || dayOfWeek === 6 } export const Unavailable = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const isWeekend = (date: DateValue) => { const dayOfWeek = date.toDate('UTC').getDay() return dayOfWeek === 0 || dayOfWeek === 6 } export const Unavailable = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Locale Use the `locale` prop to set the language and formatting, and `startOfWeek` to set the first day of the week (0 = Sunday, 1 = Monday, etc.). **Example: locale** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Locale = () => { return ( Datum auswählen Löschen {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Locale = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Month Picker Create a month-only picker by setting `defaultView="month"` and `minView="month"`. Use custom `format` and `parse` functions to handle month/year input format. **Example: month-picker** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPicker = () => { return ( Label Clear {(datePicker) => ( {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPicker = () => { return ( Label Clear {(context) => ( {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Year Picker Create a year-only picker by setting `defaultView="year"` and `minView="year"`. Use custom `format` and `parse` functions to handle year-only input format. **Example: year-picker** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (string === '' || !string) return const year = Number(string) if (year < 100) { const currentYear = new Date().getFullYear() const currentCentury = Math.floor(currentYear / 100) * 100 return parseDate(new Date(currentCentury + year, 0)) } return parseDate(new Date(Number(string), 0)) } export const YearPicker = () => { return ( Label Clear {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (string === '' || !string) return const year = Number(string) if (year < 100) { const currentYear = new Date().getFullYear() const currentCentury = Math.floor(currentYear / 100) * 100 return parseDate(new Date(currentCentury + year, 0)) } return parseDate(new Date(Number(string), 0)) } export const YearPicker = () => { return ( Label Clear {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Inline Use the `inline` prop to display the date picker directly on the page, without a popup. > When using the `inline` prop, omit the `Portal`, `Positioner`, and `Content` components to render the calendar inline > within your layout. **Example: inline** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import styles from 'styles/date-picker.module.css' export const Inline = () => { return (
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/date-picker.module.css' export const Inline = () => { return ( {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Custom Parsing Use the `parse` prop to implement custom date parsing logic. This allows users to enter dates in flexible formats like "25/12" or "25/12/24" which are automatically converted to valid dates. **Example: format-parse** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const parse = (value: string) => { const fullRegex = /^(\d{1,2})\/(\d{1,2})\/(\d{2})$/ const fullMatch = value.match(fullRegex) if (fullMatch) { const [_, day, month, year] = fullMatch.map(Number) try { return new CalendarDate(year + 2000, month, day) } catch { return undefined } } const partialRegex = /^(\d{1,2})\/(\d{1,2})$/ const partialMatch = value.match(partialRegex) if (partialMatch) { const [_, day, month] = partialMatch.map(Number) const currentYear = new Date().getFullYear() try { return new CalendarDate(currentYear, month, day) } catch { return undefined } } const dayRegex = /^(\d{1,2})$/ const dayMatch = value.match(dayRegex) if (dayMatch) { const [_, day] = dayMatch.map(Number) const currentYear = new Date().getFullYear() return new CalendarDate(currentYear, 1, day) } return undefined } const format = (date: DateValue) => { const day = date.day.toString().padStart(2, '0') const month = date.month.toString().padStart(2, '0') const year = (date.year % 100).toString().padStart(2, '0') return `${day}/${month}/${year}` } export const FormatParse = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` ### Month Picker Range Create a month range picker by combining `selectionMode="range"` with `defaultView="month"` and `minView="month"`. This is useful for selecting billing periods or date ranges by month. **Example: month-picker-range** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPickerRange = () => { return ( Label Clear {(datePicker) => ( {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPickerRange = () => { return ( Label Clear {(context) => ( {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Year Range Create a year range picker by combining `selectionMode="range"` with `defaultView="year"` and `minView="year"`. This is useful for selecting multi-year periods. **Example: year-picker-range** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string) => { const fullRegex = /^(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, year] = fullMatch.map(Number) return new CalendarDate(year, 1, 1) } } export const YearPickerRange = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.getDecade().start} - {datePicker.getDecade().end} {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (!string) return const fullRegex = /^(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, year] = fullMatch.map(Number) return new CalendarDate(year, 1, 1) } } export const YearPickerRange = () => { return ( Label Clear {(context) => ( <> {context().getDecade().start} - {context().getDecade().end} {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {datePicker().getDecade().start} - {datePicker().getDecade().end} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### With Time Integrate a time input with the date picker using `CalendarDateTime` from `@internationalized/date`. The time input updates the hour and minute of the selected date value. **Example: with-time** #### React ```tsx import { CalendarDateTime, DateFormatter, getLocalTimeZone } from '@internationalized/date' import { DatePicker, type DatePickerValueChangeDetails } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatter = new DateFormatter('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', }) export const WithTime = () => { const [value, setValue] = useState([new CalendarDateTime(2025, 1, 29, 14, 30)]) const timeValue = value[0] ? `${String(value[0].hour).padStart(2, '0')}:${String(value[0].minute).padStart(2, '0')}` : '' const onTimeChange = (e: React.ChangeEvent) => { const [hours, minutes] = e.currentTarget.value.split(':').map(Number) setValue((prev) => { const current = prev[0] ?? new CalendarDateTime(2025, 1, 1, 0, 0) return [current.set({ hour: hours, minute: minutes })] }) } const onDateChange = (details: DatePickerValueChangeDetails) => { const newDate = details.value[0] if (!newDate) return setValue([]) const prevTime = value[0] ?? { hour: 0, minute: 0 } setValue([new CalendarDateTime(newDate.year, newDate.month, newDate.day, prevTime.hour, prevTime.minute)]) } return ( Date and time {value[0] ? formatter.format(value[0].toDate(getLocalTimeZone())) : 'Select date and time'} {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} ) } ``` #### Solid ```tsx import { CalendarDateTime, DateFormatter, getLocalTimeZone } from '@internationalized/date' import { DatePicker, type DatePickerValueChangeDetails } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatter = new DateFormatter('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', }) export const WithTime = () => { const [value, setValue] = createSignal([new CalendarDateTime(2025, 1, 29, 14, 30)]) const timeValue = () => { const v = value()[0] return v ? `${String(v.hour).padStart(2, '0')}:${String(v.minute).padStart(2, '0')}` : '' } const onTimeChange = (e: Event & { currentTarget: HTMLInputElement }) => { const [hours, minutes] = e.currentTarget.value.split(':').map(Number) setValue((prev) => { const current = prev[0] ?? new CalendarDateTime(2025, 1, 1, 0, 0) return [current.set({ hour: hours, minute: minutes })] }) } const onDateChange = (details: DatePickerValueChangeDetails) => { const newDate = details.value[0] if (!newDate) return setValue([]) const prevTime = value()[0] ?? { hour: 0, minute: 0 } setValue([new CalendarDateTime(newDate.year, newDate.month, newDate.day, prevTime.hour, prevTime.minute)]) } return ( Date and time {value()[0] ? formatter.format(value()[0].toDate(getLocalTimeZone())) : 'Select date and time'} {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Date and time {value[0] ? formatter.format(value[0].toDate(getLocalTimeZone())) : 'Select date and time'} {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'tbody'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `(props: ParentProps<'td'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'thead'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'th'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'table'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'tr'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label(index: number): string; table(id: string): string; tableHeader(id: string): string; tableBody(id: string): string; tableRow(id: string): string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `inline` | `boolean` | No | Whether the date picker is inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `modelValue` | `DateValue[]` | No | The v-model value of the date picker | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `DatePickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Reactive` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `id` | `string` | No | | | `view` | `DateView` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `ref` | `Element` | No | | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseDatePickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'tbody'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `Snippet<[PropsFn<'td'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `ref` | `Element` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'thead'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'th'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'table'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'tr'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `view` | `DateView` | No | | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the input is focused | | `open` | `boolean` | Whether the date picker is open | | `disabled` | `boolean` | Whether the date picker is disabled | | `invalid` | `boolean` | Whether the date picker is invalid | | `inline` | `boolean` | Whether the date picker is rendered inline | | `view` | `DateView` | The current view of the date picker | | `getDaysInWeek` | `(week: number, from?: DateValue) => DateValue[]` | Returns an array of days in the week index counted from the provided start date, or the first visible date if not given. | | `getOffset` | `(duration: DateDuration) => DateValueOffset` | Returns the offset of the month based on the provided number of months. | | `getRangePresetValue` | `(value: DateRangePreset) => DateValue[]` | Returns the range of dates based on the provided date range preset. | | `getMonthWeeks` | `(from?: DateValue) => DateValue[][]` | Returns the weeks of the month from the provided date. Represented as an array of arrays of dates. | | `isUnavailable` | `(date: DateValue) => boolean` | Returns whether the provided date is available (or can be selected) | | `weeks` | `DateValue[][]` | The weeks of the month. Represented as an array of arrays of dates. | | `weekDays` | `WeekDay[]` | The days of the week. Represented as an array of strings. | | `visibleRange` | `VisibleRange` | The visible range of dates. | | `visibleRangeText` | `VisibleRangeText` | The human readable text for the visible range of dates. | | `value` | `DateValue[]` | The selected date. | | `valueAsDate` | `Date[]` | The selected date as a Date object. | | `valueAsString` | `string[]` | The selected date as a string. | | `focusedValue` | `DateValue` | The focused date. | | `focusedValueAsDate` | `Date` | The focused date as a Date object. | | `focusedValueAsString` | `string` | The focused date as a string. | | `selectToday` | `VoidFunction` | Sets the selected date to today. | | `setValue` | `(values: DateValue[]) => void` | Sets the selected date to the given date. | | `setFocusedValue` | `(value: DateValue) => void` | Sets the focused date to the given date. | | `clearValue` | `VoidFunction` | Clears the selected date(s). | | `setOpen` | `(open: boolean) => void` | Function to open or close the calendar. | | `focusMonth` | `(month: number) => void` | Function to set the selected month. | | `focusYear` | `(year: number) => void` | Function to set the selected year. | | `getYears` | `() => Cell[]` | Returns the months of the year | | `getYearsGrid` | `(props?: YearGridProps) => YearGridValue` | Returns the years of the decade based on the columns. Represented as an array of arrays of years. | | `getDecade` | `() => Range` | Returns the start and end years of the decade. | | `getMonths` | `(props?: MonthFormatOptions) => Cell[]` | Returns the months of the year | | `getMonthsGrid` | `(props?: MonthGridProps) => MonthGridValue` | Returns the months of the year based on the columns. Represented as an array of arrays of months. | | `format` | `(value: DateValue, opts?: Intl.DateTimeFormatOptions) => string` | Formats the given date value based on the provided options. | | `setView` | `(view: DateView) => void` | Sets the view of the date picker. | | `goToNext` | `VoidFunction` | Goes to the next month/year/decade. | | `goToPrev` | `VoidFunction` | Goes to the previous month/year/decade. | | `getDayTableCellState` | `(props: DayTableCellProps) => DayTableCellState` | Returns the state details for a given cell. | | `getMonthTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given month cell. | | `getYearTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given year cell. | ## Accessibility ### Keyboard Support **`ArrowLeft`** Description: Moves focus to the previous day within the current week. **`ArrowRight`** Description: Moves focus to the next day within the current week. **`ArrowUp`** Description: Moves focus to the same day of the week in the previous week. **`ArrowDown`** Description: Moves focus to the same day of the week in the next week. **`Home`** Description: Moves focus to the first day of the current month. **`End`** Description: Moves focus to the last day of the current month. **`PageUp`** Description: Moves focus to the same day of the month in the previous month. **`PageDown`** Description: Moves focus to the same day of the month in the next month. **`Enter`** Description: Selects the focused date and closes the date picker. **`Esc`** Description: Closes the date picker without selecting any date. # Date Picker (VUE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Default Value Use the `defaultValue` prop with `parseDate` to set the initial date value. **Example: default-value** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Controlled Use the `value` and `onValueChange` props to control the date picker's value programmatically. **Example: controlled** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = useState([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = createSignal([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Root Provider An alternative way to control the date picker is to use the `RootProvider` component and the `useDatePicker` hook. This way you can access the state and methods from outside the component. **Example: root-provider** #### React ```tsx import { DatePicker, useDatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RootProvider = () => { const datePicker = useDatePicker() return (
                    Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker, useDatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RootProvider = () => { const datePicker = useDatePicker() return ( <> Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Default View Use the `defaultView` prop to set which view (day, month, or year) the calendar opens to initially. **Example: default-view** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultView = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultView = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Month and Year Select Use `MonthSelect` and `YearSelect` components to create a header with dropdown selects for quick month/year navigation, alongside the prev/next triggers. **Example: month-year-select** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import styles from 'styles/date-picker.module.css' export const MonthYearSelect = () => { return ( Label {(datePicker) => ( <>
                    {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import styles from 'styles/date-picker.module.css' export const MonthYearSelect = () => { return ( Label {(context) => ( <>
                    {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label {#snippet render(datePicker)}
                    {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet}
                    ``` ### Range To create a date picker that allows a range selection, you need to: - Set the `selectionMode` prop to `range`. - Render multiple inputs with the `index` prop set to `0` and `1`. **Example: range-selection** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RangeSelection = () => { return ( Label Clear Last 7 days {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon } from 'lucide-solid' import { Index, createMemo } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const RangeSelection = () => { return ( Label Clear Last 7 days
                    {(context) => ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => { const offset = createMemo(() => context().getOffset({ months: 1 })) return ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} ) }}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear Last 7 days {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Multiple Use the `selectionMode="multiple"` prop to allow selecting multiple dates. This example also shows how to display selected dates as removable tags. **Example: multi-selection** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon, XIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatWithDay = (date: DateValue) => { const jsDate = date.toDate('UTC') return jsDate.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', }) } export const MultiSelection = () => { return ( Label {(datePicker) => (
                    {datePicker.value.length === 0 ? ( Select dates... ) : ( datePicker.value.map((date, index) => ( {formatWithDay(date)} )) )}
                    )}
                    Clear
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { For, Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultiSelection = () => { return ( Label {(context) => (
                    {context().value.length === 0 ? ( Select dates... ) : ( {(date, index) => ( {date.toDate('UTC').toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', })} )} )}
                    )}
                    Clear
                    {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Multiple Months To create a date picker that displays multiple months side by side: - Set the `numOfMonths` prop to the number of months you want to display. - Use the `datePicker.getOffset({ months: 1 })` to get data for the next month. **Example: multiple-months** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultipleMonths = () => { return ( Label Clear
                    {(datePicker) => ( {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => { const offset = datePicker.getOffset({ months: 1 }) return ( {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {offset.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} ) }}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createMemo } from 'solid-js' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MultipleMonths = () => { return ( Label Clear
                    {(datePicker) => ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(datePicker) => { const offset = createMemo(() => datePicker().getOffset({ months: 1 })) return ( {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} ) }}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear
                    {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay, id (id)} {weekDay.short} {/each} {#each datePicker().weeks as week, id} {#each week as day, id (id)} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {@const offset = datePicker().getOffset({ months: 1 })} {#each datePicker().weekDays as weekDay, id (id)} {weekDay.short} {/each} {#each offset.weeks as week, id (id)} {#each week as day, id (id)} {day.day} {/each} {/each} {/snippet}
                    ``` ### Presets Use the `DatePicker.PresetTrigger` component to add quick-select preset options like "Last 7 days" or "This month". **Example: presets** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Presets = () => { return ( Label Clear
                    Last 7 days Last 30 days This month Last month
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Presets = () => { return ( Label Clear
                    Last 7 days Last 30 days This month
                    {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )}
                    ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear
                    Last 7 days Last 30 days This month
                    {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet}
                    ``` ### Min and Max Use the `min` and `max` props with `parseDate` to restrict the selectable date range. Dates outside this range will be disabled. **Example: min-max** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MinMax = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const MinMax = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Unavailable Use the `isDateUnavailable` prop to mark specific dates as unavailable. This example disables weekends. **Example: unavailable** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const isWeekend = (date: DateValue) => { const dayOfWeek = date.toDate('UTC').getDay() return dayOfWeek === 0 || dayOfWeek === 6 } export const Unavailable = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const isWeekend = (date: DateValue) => { const dayOfWeek = date.toDate('UTC').getDay() return dayOfWeek === 0 || dayOfWeek === 6 } export const Unavailable = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Locale Use the `locale` prop to set the language and formatting, and `startOfWeek` to set the first day of the week (0 = Sunday, 1 = Monday, etc.). **Example: locale** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Locale = () => { return ( Datum auswählen Löschen {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Locale = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Month Picker Create a month-only picker by setting `defaultView="month"` and `minView="month"`. Use custom `format` and `parse` functions to handle month/year input format. **Example: month-picker** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPicker = () => { return ( Label Clear {(datePicker) => ( {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPicker = () => { return ( Label Clear {(context) => ( {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Year Picker Create a year-only picker by setting `defaultView="year"` and `minView="year"`. Use custom `format` and `parse` functions to handle year-only input format. **Example: year-picker** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import type { DateValue } from '@internationalized/date' import { CalendarIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (string === '' || !string) return const year = Number(string) if (year < 100) { const currentYear = new Date().getFullYear() const currentCentury = Math.floor(currentYear / 100) * 100 return parseDate(new Date(currentCentury + year, 0)) } return parseDate(new Date(Number(string), 0)) } export const YearPicker = () => { return ( Label Clear {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import type { DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (string === '' || !string) return const year = Number(string) if (year < 100) { const currentYear = new Date().getFullYear() const currentCentury = Math.floor(currentYear / 100) * 100 return parseDate(new Date(currentCentury + year, 0)) } return parseDate(new Date(Number(string), 0)) } export const YearPicker = () => { return ( Label Clear {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Inline Use the `inline` prop to display the date picker directly on the page, without a popup. > When using the `inline` prop, omit the `Portal`, `Positioner`, and `Content` components to render the calendar inline > within your layout. **Example: inline** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import styles from 'styles/date-picker.module.css' export const Inline = () => { return (
                    {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )}
                    ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import styles from 'styles/date-picker.module.css' export const Inline = () => { return ( {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Custom Parsing Use the `parse` prop to implement custom date parsing logic. This allows users to enter dates in flexible formats like "25/12" or "25/12/24" which are automatically converted to valid dates. **Example: format-parse** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const parse = (value: string) => { const fullRegex = /^(\d{1,2})\/(\d{1,2})\/(\d{2})$/ const fullMatch = value.match(fullRegex) if (fullMatch) { const [_, day, month, year] = fullMatch.map(Number) try { return new CalendarDate(year + 2000, month, day) } catch { return undefined } } const partialRegex = /^(\d{1,2})\/(\d{1,2})$/ const partialMatch = value.match(partialRegex) if (partialMatch) { const [_, day, month] = partialMatch.map(Number) const currentYear = new Date().getFullYear() try { return new CalendarDate(currentYear, month, day) } catch { return undefined } } const dayRegex = /^(\d{1,2})$/ const dayMatch = value.match(dayRegex) if (dayMatch) { const [_, day] = dayMatch.map(Number) const currentYear = new Date().getFullYear() return new CalendarDate(currentYear, 1, day) } return undefined } const format = (date: DateValue) => { const day = date.day.toString().padStart(2, '0') const month = date.month.toString().padStart(2, '0') const year = (date.year % 100).toString().padStart(2, '0') return `${day}/${month}/${year}` } export const FormatParse = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` ### Month Picker Range Create a month range picker by combining `selectionMode="range"` with `defaultView="month"` and `minView="month"`. This is useful for selecting billing periods or date ranges by month. **Example: month-picker-range** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPickerRange = () => { return ( Label Clear {(datePicker) => ( {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => { const month = date.month.toString().padStart(2, '0') const year = date.year.toString() return `${month}/${year}` } const parse = (string: string) => { const fullRegex = /^(\d{1,2})\/(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, month, year] = fullMatch.map(Number) return new CalendarDate(year, month, 1) } } export const MonthPickerRange = () => { return ( Label Clear {(context) => ( {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Year Range Create a year range picker by combining `selectionMode="range"` with `defaultView="year"` and `minView="year"`. This is useful for selecting multi-year periods. **Example: year-picker-range** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string) => { const fullRegex = /^(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, year] = fullMatch.map(Number) return new CalendarDate(year, 1, 1) } } export const YearPickerRange = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.getDecade().start} - {datePicker.getDecade().end} {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarDate, type DateValue } from '@internationalized/date' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const format = (date: DateValue) => date.year.toString() const parse = (string: string | undefined) => { if (!string) return const fullRegex = /^(\d{4})$/ const fullMatch = string.match(fullRegex) if (fullMatch) { const [_, year] = fullMatch.map(Number) return new CalendarDate(year, 1, 1) } } export const YearPickerRange = () => { return ( Label Clear {(context) => ( <> {context().getDecade().start} - {context().getDecade().end} {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {datePicker().getDecade().start} - {datePicker().getDecade().end} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### With Time Integrate a time input with the date picker using `CalendarDateTime` from `@internationalized/date`. The time input updates the hour and minute of the selected date value. **Example: with-time** #### React ```tsx import { CalendarDateTime, DateFormatter, getLocalTimeZone } from '@internationalized/date' import { DatePicker, type DatePickerValueChangeDetails } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatter = new DateFormatter('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', }) export const WithTime = () => { const [value, setValue] = useState([new CalendarDateTime(2025, 1, 29, 14, 30)]) const timeValue = value[0] ? `${String(value[0].hour).padStart(2, '0')}:${String(value[0].minute).padStart(2, '0')}` : '' const onTimeChange = (e: React.ChangeEvent) => { const [hours, minutes] = e.currentTarget.value.split(':').map(Number) setValue((prev) => { const current = prev[0] ?? new CalendarDateTime(2025, 1, 1, 0, 0) return [current.set({ hour: hours, minute: minutes })] }) } const onDateChange = (details: DatePickerValueChangeDetails) => { const newDate = details.value[0] if (!newDate) return setValue([]) const prevTime = value[0] ?? { hour: 0, minute: 0 } setValue([new CalendarDateTime(newDate.year, newDate.month, newDate.day, prevTime.hour, prevTime.minute)]) } return ( Date and time {value[0] ? formatter.format(value[0].toDate(getLocalTimeZone())) : 'Select date and time'} {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} ) } ``` #### Solid ```tsx import { CalendarDateTime, DateFormatter, getLocalTimeZone } from '@internationalized/date' import { DatePicker, type DatePickerValueChangeDetails } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' const formatter = new DateFormatter('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', }) export const WithTime = () => { const [value, setValue] = createSignal([new CalendarDateTime(2025, 1, 29, 14, 30)]) const timeValue = () => { const v = value()[0] return v ? `${String(v.hour).padStart(2, '0')}:${String(v.minute).padStart(2, '0')}` : '' } const onTimeChange = (e: Event & { currentTarget: HTMLInputElement }) => { const [hours, minutes] = e.currentTarget.value.split(':').map(Number) setValue((prev) => { const current = prev[0] ?? new CalendarDateTime(2025, 1, 1, 0, 0) return [current.set({ hour: hours, minute: minutes })] }) } const onDateChange = (details: DatePickerValueChangeDetails) => { const newDate = details.value[0] if (!newDate) return setValue([]) const prevTime = value()[0] ?? { hour: 0, minute: 0 } setValue([new CalendarDateTime(newDate.year, newDate.month, newDate.day, prevTime.hour, prevTime.minute)]) } return ( Date and time {value()[0] ? formatter.format(value()[0].toDate(getLocalTimeZone())) : 'Select date and time'} {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Date and time {value[0] ? formatter.format(value[0].toDate(getLocalTimeZone())) : 'Select date and time'} {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} ``` ## API Reference ### Props **Component API Reference** #### React **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Solid **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'input'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'label'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'tbody'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `(props: ParentProps<'td'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'thead'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'th'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'table'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'tr'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'button'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `(props: ParentProps<'select'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Vue **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label(index: number): string; table(id: string): string; tableHeader(id: string): string; tableBody(id: string): string; tableRow(id: string): string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `inline` | `boolean` | No | Whether the date picker is inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `modelValue` | `DateValue[]` | No | The v-model value of the date picker | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `DatePickerApi` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `Reactive` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `id` | `string` | No | | | `view` | `DateView` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `view` | `DateView` | Yes | | | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. | #### Svelte **Root Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `closeOnSelect` | `boolean` | No | Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. | | `defaultFocusedValue` | `DateValue` | No | The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. | | `defaultOpen` | `boolean` | No | The initial open state of the date picker when rendered. Use when you don't need to control the open state of the date picker. | | `defaultValue` | `DateValue[]` | No | The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. | | `defaultView` | `DateView` | No | The default view of the calendar | | `disabled` | `boolean` | No | Whether the calendar is disabled. | | `fixedWeeks` | `boolean` | No | Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. | | `focusedValue` | `DateValue` | No | The controlled focused date. | | `format` | `(date: DateValue, details: LocaleDetails) => string` | No | The format of the date to display in the input. | | `id` | `string` | No | The unique identifier of the machine. | | `ids` | `Partial<{ root: string; label: (index: number) => string; table: (id: string) => string; tableHeader: (id: string) => string; tableBody: (id: string) => string; tableRow: (id: string) => string; content: string; ... 10 more ...; positioner: string; }>` | No | The ids of the elements in the date picker. Useful for composition. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `inline` | `boolean` | No | Whether to render the date picker inline | | `isDateUnavailable` | `(date: DateValue, locale: string) => boolean` | No | Returns whether a date of the calendar is available. | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `locale` | `string` | No | The locale (BCP 47 language tag) to use when formatting the date. | | `max` | `DateValue` | No | The maximum date that can be selected. | | `maxView` | `DateView` | No | The maximum view of the calendar | | `min` | `DateValue` | No | The minimum date that can be selected. | | `minView` | `DateView` | No | The minimum view of the calendar | | `name` | `string` | No | The `name` attribute of the input element. | | `numOfMonths` | `number` | No | The number of months to display. | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function called when the focused date changes. | | `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the calendar opens or closes. | | `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function called when the value changes. | | `onViewChange` | `(details: ViewChangeDetails) => void` | No | Function called when the view changes. | | `open` | `boolean` | No | The controlled open state of the date picker | | `outsideDaySelectable` | `boolean` | No | Whether day outside the visible range can be selected. | | `parse` | `(value: string, details: LocaleDetails) => DateValue | undefined` | No | Function to parse the date from the input back to a DateValue. | | `placeholder` | `string` | No | The placeholder text to display in the input. | | `positioning` | `PositioningOptions` | No | The user provided options used to position the date picker content | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `readOnly` | `boolean` | No | Whether the calendar is read-only. | | `ref` | `Element` | No | | | `selectionMode` | `SelectionMode` | No | The selection mode of the calendar. - `single` - only one date can be selected - `multiple` - multiple dates can be selected - `range` - a range of dates can be selected | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `startOfWeek` | `number` | No | The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday | | `timeZone` | `string` | No | The time zone to use | | `translations` | `IntlTranslations` | No | The localized messages to use. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | | `value` | `DateValue[]` | No | The controlled selected date(s). | | `view` | `DateView` | No | The view of the calendar | **Root Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | root | | `[data-state]` | "open" | "closed" | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **ClearTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Content Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | content | | `[data-state]` | "open" | "closed" | | `[data-nested]` | popover | | `[data-has-nested]` | popover | | `[data-placement]` | The placement of the content | | `[data-inline]` | Present when the content is inline | **Content CSS Variables:** | Variable | Description | |----------|-------------| | `--layer-index` | The index of the dismissable in the layer stack | | `--nested-layer-count` | The number of nested date-pickers | **Context Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `render` | `Snippet<[UseDatePickerContext]>` | Yes | | **Control Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Control Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | control | | `[data-disabled]` | Present when disabled | **Input Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `fixOnBlur` | `boolean` | No | Whether to fix the input value on blur. | | `index` | `number` | No | The index of the input to focus. | | `ref` | `Element` | No | | **Input Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | input | | `[data-index]` | The index of the item | | `[data-state]` | "open" | "closed" | | `[data-invalid]` | Present when invalid | **Label Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Label Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | label | | `[data-state]` | "open" | "closed" | | `[data-index]` | The index of the item | | `[data-disabled]` | Present when disabled | | `[data-readonly]` | Present when read-only | **MonthSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **NextTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | next-trigger | | `[data-disabled]` | Present when disabled | **Positioner Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Positioner CSS Variables:** | Variable | Description | |----------|-------------| | `--reference-width` | The width of the reference element | | `--reference-height` | The height of the root | | `--available-width` | The available width in viewport | | `--available-height` | The available height in viewport | | `--x` | The x position for transform | | `--y` | The y position for transform | | `--z-index` | The z-index value | | `--transform-origin` | The transform origin for animations | **PresetTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `PresetTriggerValue` | Yes | | | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **PrevTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | prev-trigger | | `[data-disabled]` | Present when disabled | **RangeText Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **RootProvider Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `UseDatePickerReturn` | Yes | | | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame | | `lazyMount` | `boolean` | No | Whether to enable lazy mounting | | `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state | | `present` | `boolean` | No | Whether the node is present (controlled by the user) | | `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. | | `unmountOnExit` | `boolean` | No | Whether to unmount on exit. | **TableBody Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'tbody'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableBody Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-body | | `[data-view]` | The view of the tablebody | | `[data-disabled]` | Present when disabled | **TableCell Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `value` | `number | DateValue` | Yes | | | `asChild` | `Snippet<[PropsFn<'td'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | | `disabled` | `boolean` | No | | | `ref` | `Element` | No | | | `visibleRange` | `VisibleRange` | No | | **TableCellTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHead Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'thead'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHead Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-head | | `[data-view]` | The view of the tablehead | | `[data-disabled]` | Present when disabled | **TableHeader Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'th'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableHeader Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-header | | `[data-view]` | The view of the tableheader | | `[data-disabled]` | Present when disabled | **Table Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'table'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `columns` | `number` | No | | **Table Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table | | `[data-columns]` | | | `[data-view]` | The view of the table | **TableRow Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'tr'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **TableRow Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | table-row | | `[data-disabled]` | Present when disabled | | `[data-view]` | The view of the tablerow | **Trigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **Trigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | trigger | | `[data-placement]` | The placement of the trigger | | `[data-state]` | "open" | "closed" | **ViewControl Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ViewControl Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-control | | `[data-view]` | The view of the viewcontrol | **View Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | | `view` | `DateView` | No | | **View Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view | | `[data-view]` | The view of the view | **ViewTrigger Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | **ViewTrigger Data Attributes:** | Attribute | Value | |-----------|-------| | `[data-scope]` | date-picker | | `[data-part]` | view-trigger | | `[data-view]` | The view of the viewtrigger | **YearSelect Props:** | Prop | Type | Required | Description | |------|------|----------|-------------| | `asChild` | `Snippet<[PropsFn<'select'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. | | `ref` | `Element` | No | | ### Context **API:** | Property | Type | Description | |----------|------|-------------| | `focused` | `boolean` | Whether the input is focused | | `open` | `boolean` | Whether the date picker is open | | `disabled` | `boolean` | Whether the date picker is disabled | | `invalid` | `boolean` | Whether the date picker is invalid | | `inline` | `boolean` | Whether the date picker is rendered inline | | `view` | `DateView` | The current view of the date picker | | `getDaysInWeek` | `(week: number, from?: DateValue) => DateValue[]` | Returns an array of days in the week index counted from the provided start date, or the first visible date if not given. | | `getOffset` | `(duration: DateDuration) => DateValueOffset` | Returns the offset of the month based on the provided number of months. | | `getRangePresetValue` | `(value: DateRangePreset) => DateValue[]` | Returns the range of dates based on the provided date range preset. | | `getMonthWeeks` | `(from?: DateValue) => DateValue[][]` | Returns the weeks of the month from the provided date. Represented as an array of arrays of dates. | | `isUnavailable` | `(date: DateValue) => boolean` | Returns whether the provided date is available (or can be selected) | | `weeks` | `DateValue[][]` | The weeks of the month. Represented as an array of arrays of dates. | | `weekDays` | `WeekDay[]` | The days of the week. Represented as an array of strings. | | `visibleRange` | `VisibleRange` | The visible range of dates. | | `visibleRangeText` | `VisibleRangeText` | The human readable text for the visible range of dates. | | `value` | `DateValue[]` | The selected date. | | `valueAsDate` | `Date[]` | The selected date as a Date object. | | `valueAsString` | `string[]` | The selected date as a string. | | `focusedValue` | `DateValue` | The focused date. | | `focusedValueAsDate` | `Date` | The focused date as a Date object. | | `focusedValueAsString` | `string` | The focused date as a string. | | `selectToday` | `VoidFunction` | Sets the selected date to today. | | `setValue` | `(values: DateValue[]) => void` | Sets the selected date to the given date. | | `setFocusedValue` | `(value: DateValue) => void` | Sets the focused date to the given date. | | `clearValue` | `VoidFunction` | Clears the selected date(s). | | `setOpen` | `(open: boolean) => void` | Function to open or close the calendar. | | `focusMonth` | `(month: number) => void` | Function to set the selected month. | | `focusYear` | `(year: number) => void` | Function to set the selected year. | | `getYears` | `() => Cell[]` | Returns the months of the year | | `getYearsGrid` | `(props?: YearGridProps) => YearGridValue` | Returns the years of the decade based on the columns. Represented as an array of arrays of years. | | `getDecade` | `() => Range` | Returns the start and end years of the decade. | | `getMonths` | `(props?: MonthFormatOptions) => Cell[]` | Returns the months of the year | | `getMonthsGrid` | `(props?: MonthGridProps) => MonthGridValue` | Returns the months of the year based on the columns. Represented as an array of arrays of months. | | `format` | `(value: DateValue, opts?: Intl.DateTimeFormatOptions) => string` | Formats the given date value based on the provided options. | | `setView` | `(view: DateView) => void` | Sets the view of the date picker. | | `goToNext` | `VoidFunction` | Goes to the next month/year/decade. | | `goToPrev` | `VoidFunction` | Goes to the previous month/year/decade. | | `getDayTableCellState` | `(props: DayTableCellProps) => DayTableCellState` | Returns the state details for a given cell. | | `getMonthTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given month cell. | | `getYearTableCellState` | `(props: TableCellProps) => TableCellState` | Returns the state details for a given year cell. | ## Accessibility ### Keyboard Support **`ArrowLeft`** Description: Moves focus to the previous day within the current week. **`ArrowRight`** Description: Moves focus to the next day within the current week. **`ArrowUp`** Description: Moves focus to the same day of the week in the previous week. **`ArrowDown`** Description: Moves focus to the same day of the week in the next week. **`Home`** Description: Moves focus to the first day of the current month. **`End`** Description: Moves focus to the last day of the current month. **`PageUp`** Description: Moves focus to the same day of the month in the previous month. **`PageDown`** Description: Moves focus to the same day of the month in the next month. **`Enter`** Description: Selects the focused date and closes the date picker. **`Esc`** Description: Closes the date picker without selecting any date. # Date Picker (SVELTE) ## Anatomy ```tsx ``` ## Examples **Example: basic** #### React ```tsx import { DatePicker } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Basic = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Default Value Use the `defaultValue` prop with `parseDate` to set the initial date value. **Example: default-value** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const DefaultValue = () => { return ( Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getMonthsGrid({ columns: 4, format: 'short' }) as months} {#each months as month} {month.label} {/each} {/each} {/snippet} {#snippet render(datePicker)} {#each datePicker().getYearsGrid({ columns: 4 }) as years} {#each years as year} {year.label} {/each} {/each} {/snippet} ``` ### Controlled Use the `value` and `onValueChange` props to control the date picker's value programmatically. **Example: controlled** #### React ```tsx import { DatePicker, parseDate } from '@ark-ui/react/date-picker' import { Portal } from '@ark-ui/react/portal' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react' import { useState } from 'react' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = useState([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(datePicker) => ( <> {datePicker.weekDays.map((weekDay, id) => ( {weekDay.short} ))} {datePicker.weeks.map((week, id) => ( {week.map((day, id) => ( {day.day} ))} ))} )} {(datePicker) => ( <> {datePicker.getMonthsGrid({ columns: 4, format: 'short' }).map((months, id) => ( {months.map((month, id) => ( {month.label} ))} ))} )} {(datePicker) => ( <> {datePicker.getYearsGrid({ columns: 4 }).map((years, id) => ( {years.map((year, id) => ( {year.label} ))} ))} )} ) } ``` #### Solid ```tsx import { DatePicker, parseDate } from '@ark-ui/solid/date-picker' import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid' import { Index, createSignal } from 'solid-js' import { Portal } from 'solid-js/web' import button from 'styles/button.module.css' import styles from 'styles/date-picker.module.css' export const Controlled = () => { const [value, setValue] = createSignal([parseDate('2022-01-01')]) return ( setValue(e.value)}> Label Clear {(context) => ( <> {(weekDay) => ( {weekDay().short} )} {(week) => ( {(day) => ( {day().day} )} )} )} {(context) => ( <> {(months) => ( {(month) => ( {month().label} )} )} )} {(context) => ( <> {(years) => ( {(year) => ( {year().label} )} )} )} ) } ``` #### Vue ```vue ``` #### Svelte ```svelte Label Clear {#snippet render(datePicker)} {#each datePicker().weekDays as weekDay} {weekDay.short} {/each} {#each datePicker().weeks as week} {#each week as day} {day.day} {/each} {/each} {/snippet} {#snippet render(datePicker)}