An accordion is a vertically stacked set of interactive headings containing a title, content snippet, or thumbnail representing a section of content. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/accordion) [Logic Visualizer](https://zag-visualizer.vercel.app/accordion) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/accordion) **Features** - Full keyboard navigation - Supports single and multiple expanded items - Supports collapsible items - Supports horizontal and vertical orientation ## Installation Install the accordion package: ```bash npm install @zag-js/accordion @zag-js/vue # or yarn add @zag-js/accordion @zag-js/vue ``` ## Anatomy Check the accordion anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the accordion package: ```jsx import * as accordion from "@zag-js/accordion" ``` The accordion package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` You may have noticed we wrapped each accordion trigger within an `h3`. This is recommended by the [WAI-ARIA](https://www.w3.org/TR/wai-aria-practices-1.1/#wai-aria-roles-states-and-properties) design pattern to ensure the accordion has the appropriate hierarchy on the page. ### Opening multiple items Set `multiple` to `true` to allow more than one expanded item at a time. ```jsx {2} const service = useMachine(accordion.machine, { multiple: true, }) ``` ### Setting the initial value Set `defaultValue` to define expanded items on first render. ```jsx // multiple mode const service = useMachine(accordion.machine, { multiple: true, defaultValue: ["home", "about"], }) // single mode const service = useMachine(accordion.machine, { defaultValue: ["home"], }) ``` ### Controlled accordions Use `value` and `onValueChange` to control expanded items externally. ```html ``` ### Making items collapsible Set `collapsible` to `true` to allow closing an expanded item by clicking it again. > Note: If `multiple` is `true`, we internally set `collapsible` to be `true`. ```jsx {2} const service = useMachine(accordion.machine, { collapsible: true, }) ``` ### Listening for value changes When the accordion value changes, the `onValueChange` callback is invoked. ```jsx {2-5} const service = useMachine(accordion.machine, { onValueChange(details) { // details => { value: string[] } console.log("selected accordion:", details.value) }, }) ``` ### Listening for focus changes Use `onFocusChange` to react when keyboard focus moves between item triggers. ```jsx const service = useMachine(accordion.machine, { onFocusChange(details) { // details => { value: string | null } console.log("focused item:", details.value) }, }) ``` ### Horizontal orientation Set `orientation` to `horizontal` when rendering items side by side. ```jsx {2} const service = useMachine(accordion.machine, { orientation: "horizontal", }) ``` ### Disabling an accordion item To disable a specific accordion item, pass the `disabled: true` property to the `getItemProps`, `getItemTriggerProps` and `getItemContentProps`. When an accordion item is disabled, it is skipped from keyboard navigation and can't be interacted with. ```jsx //...

Content
//... ``` You can also disable the entire accordion by setting `disabled` on the machine. ```jsx {2} const service = useMachine(accordion.machine, { disabled: true, }) ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ### Open and closed state When an accordion item expands or collapses, `data-state` is set to `open` or `closed` on the item, trigger, and content elements. ```css [data-part="item"][data-state="open|closed"] { /* styles for the item is open or closed state */ } [data-part="item-trigger"][data-state="open|closed"] { /* styles for the item is open or closed state */ } [data-part="item-content"][data-state="open|closed"] { /* styles for the item is open or closed state */ } ``` ### Focused state When an accordion item's trigger is focused, a `data-focus` attribute is set on the item and content. ```css [data-part="item"][data-focus] { /* styles for the item's focus state */ } [data-part="item-trigger"]:focus { /* styles for the trigger's focus state */ } [data-part="item-content"][data-focus] { /* styles for the content's focus state */ } ``` ## Creating a component Create your accordion component by abstracting the machine into your own component. ### Usage ### Implementation Use the `splitProps` utility to separate the machine's props from the component's props. ## Methods and Properties The accordion's `api` exposes the following methods and properties: ### Machine Context The accordion machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; item: (value: string) => string; itemContent: (value: string) => string; itemTrigger: (value: string) => string; }>` Description: The ids of the elements in the accordion. Useful for composition. **`multiple`** Type: `boolean` Description: Whether multiple accordion items can be expanded at the same time. **`collapsible`** Type: `boolean` Description: Whether an accordion item can be closed after it has been expanded. **`value`** Type: `string[]` Description: The controlled value of the expanded accordion items. **`defaultValue`** Type: `string[]` Description: The initial value of the expanded accordion items. Use when you don't need to control the value of the accordion. **`disabled`** Type: `boolean` Description: Whether the accordion items are disabled **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: The callback fired when the state of expanded/collapsed accordion items changes. **`onFocusChange`** Type: `(details: FocusChangeDetails) => void` Description: The callback fired when the focused accordion item changes. **`orientation`** Type: `"horizontal" | "vertical"` Description: The orientation of the accordion items. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. ### Machine API The accordion `api` exposes the following methods: **`focusedValue`** Type: `string` Description: The value of the focused accordion item. **`value`** Type: `string[]` Description: The value of the accordion **`setValue`** Type: `(value: string[]) => void` Description: Sets the value of the accordion **`getItemState`** Type: `(props: ItemProps) => ItemState` Description: Returns the state of an accordion item. ### Data Attributes **`Root`** **`data-scope`**: accordion **`data-part`**: root **`data-orientation`**: The orientation of the accordion **`Item`** **`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 **`ItemContent`** **`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`** **`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 **`ItemTrigger`** **`data-scope`**: accordion **`data-part`**: item-trigger **`data-controls`**: **`data-orientation`**: The orientation of the item **`data-state`**: "open" | "closed" ## Accessibility ### Keyboard Interactions **`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. An angle slider is a circular dial that allows users to select an angle, typically in degrees, within a 360° range. It provides an intuitive way to control rotations or orientations, offering accessibility features. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/angle-slider) [Logic Visualizer](https://zag-visualizer.vercel.app/angle-slider) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/angle-slider) **Features** - Fully managed keyboard navigation - Supports touch or click on the track to update value - Supports right-to-left direction ## Installation Install the angle slider package: ```bash npm install @zag-js/angle-slider @zag-js/vue # or yarn add @zag-js/angle-slider @zag-js/vue ``` ## Anatomy To set up the angle slider correctly, you'll need to understand its anatomy and how we name its parts. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the angle-slider package: ```jsx import * as angleSlider from "@zag-js/angle-slider" ``` The angle slider package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Setting the initial value Set `defaultValue` to define the initial slider value. ```jsx {2} const service = useMachine(angleSlider.machine, { defaultValue: 45, }) ``` ### Controlled angle slider Use `value` and `onValueChange` to control the value externally. ```html ``` ### Setting the value's granularity By default, `step` is `1`, so values move in whole-number increments. Set `step` to control granularity. For example, set `step` to `0.01` for two-decimal precision: ```jsx {2} const service = useMachine(angleSlider.machine, { step: 0.01, }) ``` ### Listening for changes When the angle slider value changes, the `onValueChange` and `onValueChangeEnd` callbacks are invoked. ```jsx {2-7} const service = useMachine(angleSlider.machine, { onValueChange(details) { console.log("value:", details.value) console.log("as degree:", details.valueAsDegree) }, onValueChangeEnd(details) { console.log("final value:", details.value) }, }) ``` ### Read-only mode Set `readOnly` to prevent updates while preserving focus and form semantics. ```jsx {2} const service = useMachine(angleSlider.machine, { readOnly: true, }) ``` ### Usage in forms To submit the value with a form: - Set `name` on the machine. - Render the hidden input from `api.getHiddenInputProps()`. ```jsx {2} const service = useMachine(angleSlider.machine, { name: "wind-direction", }) ``` ### Labeling the thumb for assistive tech Use `aria-label` or `aria-labelledby` when you need custom labeling. ```jsx {2} const service = useMachine(angleSlider.machine, { "aria-label": "Wind direction", }) ``` ### Using angle slider marks To show marks or ticks along the angle slider track, use the exposed `api.getMarkerProps()` method to position the angle slider marks at desired angles. ```html {10-16} //...
//... ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ### Disabled State When the angle slider is disabled, the `data-disabled` attribute is added to the root, label, control, thumb and marker. ```css [data-part="root"][data-disabled] { /* styles for root disabled state */ } [data-part="label"][data-disabled] { /* styles for label disabled state */ } [data-part="control"][data-disabled] { /* styles for control disabled state */ } [data-part="thumb"][data-disabled] { /* styles for thumb disabled state */ } [data-part="range"][data-disabled] { /* styles for thumb disabled state */ } ``` ### Invalid State When the slider is invalid, the `data-invalid` attribute is added to the root, track, range, label, and thumb parts. ```css [data-part="root"][data-invalid] { /* styles for root invalid state */ } [data-part="label"][data-invalid] { /* styles for label invalid state */ } [data-part="control"][data-invalid] { /* styles for control invalid state */ } [data-part="valueText"][data-invalid] { /* styles for output invalid state */ } [data-part="thumb"][data-invalid] { /* styles for thumb invalid state */ } [data-part="marker"][data-invalid] { /* styles for marker invalid state */ } ``` ### Styling the markers ```css [data-part="marker"][data-state="(at|under|over)-value"] { /* styles for when the value exceeds the marker's value */ } ``` ## Methods and Properties ### Machine Context The angle slider machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: string; label: string; }>` Description: The ids of the elements in the machine. Useful for composition. **`step`** Type: `number` Description: The step value for the slider. **`value`** Type: `number` Description: The value of the slider. **`defaultValue`** Type: `number` Description: The initial value of the slider. Use when you don't need to control the value of the slider. **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: The callback function for when the value changes. **`onValueChangeEnd`** Type: `(details: ValueChangeDetails) => void` Description: The callback function for when the value changes ends. **`disabled`** Type: `boolean` Description: Whether the slider is disabled. **`readOnly`** Type: `boolean` Description: Whether the slider is read-only. **`invalid`** Type: `boolean` Description: Whether the slider is invalid. **`name`** Type: `string` Description: The name of the slider. Useful for form submission. **`aria-label`** Type: `string` Description: The accessible label for the slider thumb. **`aria-labelledby`** Type: `string` Description: The id of the element that labels the slider thumb. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. ### Machine API The angle slider `api` exposes the following methods: **`value`** Type: `number` Description: The current value of the angle slider **`valueAsDegree`** Type: `string` Description: The current value as a degree string **`setValue`** Type: `(value: number) => void` Description: Sets the value of the angle slider **`dragging`** Type: `boolean` Description: Whether the slider is being dragged. ### Data Attributes **`Root`** **`data-scope`**: angle-slider **`data-part`**: root **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`Label`** **`data-scope`**: angle-slider **`data-part`**: label **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`Control`** **`data-scope`**: angle-slider **`data-part`**: control **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`Thumb`** **`data-scope`**: angle-slider **`data-part`**: thumb **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`Marker`** **`data-scope`**: angle-slider **`data-part`**: marker **`data-value`**: The value of the item **`data-state`**: **`data-disabled`**: Present when disabled ### CSS Variables ### Keyboard Interactions **`ArrowRight`** Description: Increments the angle slider based on defined step **`ArrowLeft`** Description: Decrements the angle slider based on defined step **`ArrowUp`** Description: Decreases the value by the step amount. **`ArrowDown`** Description: Increases the value by the step amount. **`Shift + ArrowUp`** Description: Decreases the value by a larger step **`Shift + ArrowDown`** Description: Increases the value by a larger step **`Home`** Description: Sets the value to 0 degrees. **`End`** Description: Sets the value to 360 degrees. An avatar represents a user profile picture. It displays an image or fallback content in a container. Avatar supports fallback text or elements when the image fails to load or when no image is provided. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/avatar) [Logic Visualizer](https://zag-visualizer.vercel.app/avatar) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/avatar) ## Installation Install the avatar package: ```bash npm install @zag-js/avatar @zag-js/vue # or yarn add @zag-js/avatar @zag-js/vue ``` ## Anatomy Check the avatar anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the avatar package: ```jsx import * as avatar from "@zag-js/avatar" ``` The avatar package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Listening for loading status changes When the image loads or fails, `onStatusChange` is invoked. ```jsx {2} const service = useMachine(avatar.machine, { onStatusChange(details) { // details => { status: "error" | "loaded" } }, }) ``` ### Updating the image source programmatically Use `api.setSrc` when the image source changes after mount. ```jsx api.setSrc(nextSrc) ``` ## Styling guide Each avatar part includes a `data-part` attribute you can target in CSS. ```css [data-scope="avatar"][data-part="root"] { /* Styles for the root part */ } [data-scope="avatar"][data-part="image"] { /* Styles for the image part */ } [data-scope="avatar"][data-part="fallback"] { /* Styles for the fallback part */ } ``` ## Creating a component Create your avatar component by abstracting the machine into your own component. ### Usage ### Implementation Use the `splitProps` utility to separate the machine's props from the component's props. ## Methods and Properties ### Machine Context The avatar machine exposes the following context properties: **`onStatusChange`** Type: `(details: StatusChangeDetails) => void` Description: Functional called when the image loading status changes. **`ids`** Type: `Partial<{ root: string; image: string; fallback: string; }>` Description: The ids of the elements in the avatar. Useful for composition. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. ### Machine API The avatar `api` exposes the following methods: **`loaded`** Type: `boolean` Description: Whether the image is loaded. **`setSrc`** Type: `(src: string) => void` Description: Function to set new src. **`setLoaded`** Type: `VoidFunction` Description: Function to set loaded state. **`setError`** Type: `VoidFunction` Description: Function to set error state. ### Data Attributes **`Image`** **`data-scope`**: avatar **`data-part`**: image **`data-state`**: "visible" | "hidden" **`Fallback`** **`data-scope`**: avatar **`data-part`**: fallback **`data-state`**: "hidden" | "visible" A carousel component that leverages native CSS Scroll Snap for smooth, performant scrolling between slides. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/carousel) [Logic Visualizer](https://zag-visualizer.vercel.app/carousel) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/carousel) **Features** - Uses native CSS Scroll Snap - Supports horizontal and vertical orientations - Supports slide alignment (`start`, `center`, `end`) - Supports showing multiple slides at a time - Supports looping and auto-playing - Supports custom spacing between slides ## Installation Install the carousel package: ```bash npm install @zag-js/carousel @zag-js/vue # or yarn add @zag-js/carousel @zag-js/vue ``` ## Anatomy Check the carousel anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the carousel package: ```jsx import * as carousel from "@zag-js/carousel" ``` The carousel package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: > **Note:** The carousel requires that you provide a `slideCount` property in > the machine context. This is the total number of slides. ```html ``` ### Vertical orientation Set `orientation` to `vertical` to render a vertical carousel. ```jsx {2} const service = useMachine(carousel.machine, { orientation: "vertical", }) ``` ### Setting the initial slide Set `defaultPage` to define the initial page. > The `defaultPage` corresponds to the scroll snap position index based on the > layout. It does not necessarily correspond to the index of the slide in the > carousel. ```jsx {2} const service = useMachine(carousel.machine, { defaultPage: 2, }) ``` ### Controlling the current page Use `page` and `onPageChange` for controlled navigation. ```jsx const service = useMachine(carousel.machine, { slideCount: 8, page, onPageChange(details) { setPage(details.page) }, }) ``` ### Setting slides per page Set `slidesPerPage` to control how many slides are visible per page. ```jsx {2} const service = useMachine(carousel.machine, { slidesPerPage: 2, }) ``` ### Setting slides per move Set `slidesPerMove` to control how many slides advance on next/previous. ```jsx {2} const service = useMachine(carousel.machine, { slidesPerMove: 2, }) ``` **Considerations** - If the value is `auto`, the carousel will move the number of slides equal to the number of slides per page. - Ensure the `slidesPerMove` is less than or equal to the `slidesPerPage` to avoid skipping slides. - On touch devices, `slidesPerMove` is not enforced during active swiping. The browser's native scrolling and CSS Scroll Snap determine slide movement for optimal performance and UX. ### Looping pages Set `loop` to `true` to wrap around from last to first page. ```jsx {2} const service = useMachine(carousel.machine, { loop: true, }) ``` ### Setting the gap between slides Set `spacing` to control the gap between slides. ```jsx {2} const service = useMachine(carousel.machine, { spacing: "16px", }) ``` ### Setting viewport padding Set `padding` to keep neighboring slides partially visible. ```jsx {2} const service = useMachine(carousel.machine, { padding: "16px", }) ``` ### Variable-width slides Set `autoSize` to `true` when slides have different widths. ```jsx {2} const service = useMachine(carousel.machine, { autoSize: true, }) ``` ### Listening for page changes When the carousel page changes, the `onPageChange` callback is invoked. ```jsx {2-5} const service = useMachine(carousel.machine, { onPageChange(details) { // details => { page: number } console.log("selected page:", details.page) }, }) ``` ### Listening for drag and autoplay status Use status callbacks to react to dragging and autoplay lifecycle changes. ```jsx const service = useMachine(carousel.machine, { onDragStatusChange(details) { console.log(details.type, details.isDragging) }, onAutoplayStatusChange(details) { console.log(details.type, details.isPlaying) }, }) ``` ### Dragging the carousel Set `allowMouseDrag` to `true` to drag the carousel with a mouse. ```jsx {2} const service = useMachine(carousel.machine, { allowMouseDrag: true, }) ``` ### Autoplaying the carousel Set `autoplay` to `true` to start automatic slide movement. ```jsx {2} const service = useMachine(carousel.machine, { autoplay: true, }) ``` Alternatively, you can configure the autoplay interval by setting the `delay` property. ```jsx {2} const service = useMachine(carousel.machine, { autoplay: { delay: 2000 }, }) ``` ### Customizing accessibility messages Use `translations` to customize localized trigger, item, and progress text. ```jsx const service = useMachine(carousel.machine, { slideCount: 5, translations: { nextTrigger: "Next slide", prevTrigger: "Previous slide", indicator: (index) => `Go to slide ${index + 1}`, item: (index, count) => `Slide ${index + 1} of ${count}`, autoplayStart: "Start autoplay", autoplayStop: "Stop autoplay", progressText: ({ page, totalPages }) => `Page ${page + 1} of ${totalPages}`, }, }) ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ```css [data-part="root"] { /* styles for the root part */ } [data-part="item-group"] { /* styles for the item-group part */ } [data-part="item"] { /* styles for the root part */ } [data-part="control"] { /* styles for the control part */ } [data-part="next-trigger"] { /* styles for the next-trigger part */ } [data-part="prev-trigger"] { /* styles for the prev-trigger part */ } [data-part="indicator-group"] { /* styles for the indicator-group part */ } [data-part="indicator"] { /* styles for the indicator part */ } [data-part="autoplay-trigger"] { /* styles for the autoplay-trigger part */ } ``` ### Active state When a carousel's indicator is active, a `data-current` attribute is set on the indicator. ```css [data-part="indicator"][data-current] { /* styles for the indicator's active state */ } ``` ## Methods and Properties The carousel's `api` exposes the following methods and properties: ### Machine Context The carousel machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; item: (index: number) => string; itemGroup: string; nextTrigger: string; prevTrigger: string; indicatorGroup: string; indicator: (index: number) => string; }>` Description: The ids of the elements in the carousel. Useful for composition. **`translations`** Type: `IntlTranslations` Description: The localized messages to use. **`slidesPerPage`** Type: `number` Description: The number of slides to show at a time. **`autoSize`** Type: `boolean` Description: Whether to enable variable width slides. **`slidesPerMove`** Type: `number | "auto"` Description: 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. **`autoplay`** Type: `boolean | { delay: number; }` Description: Whether to scroll automatically. The default delay is 4000ms. **`allowMouseDrag`** Type: `boolean` Description: Whether to allow scrolling via dragging with mouse **`loop`** Type: `boolean` Description: Whether the carousel should loop around. **`page`** Type: `number` Description: The controlled page of the carousel. **`defaultPage`** Type: `number` Description: The initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. **`spacing`** Type: `string` Description: The amount of space between items. **`padding`** Type: `string` Description: Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. **`onPageChange`** Type: `(details: PageChangeDetails) => void` Description: Function called when the page changes. **`inViewThreshold`** Type: `number | number[]` Description: The threshold for determining if an item is in view. **`snapType`** Type: `"proximity" | "mandatory"` Description: The snap type of the item. **`slideCount`** Type: `number` Description: The total number of slides. Useful for SSR to render the initial ating the snap points. **`onDragStatusChange`** Type: `(details: DragStatusDetails) => void` Description: Function called when the drag status changes. **`onAutoplayStatusChange`** Type: `(details: AutoplayStatusDetails) => void` Description: Function called when the autoplay status changes. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`orientation`** Type: `"horizontal" | "vertical"` Description: The orientation of the element. ### Machine API The carousel `api` exposes the following methods: **`page`** Type: `number` Description: The current index of the carousel **`pageSnapPoints`** Type: `number[]` Description: The current snap points of the carousel **`isPlaying`** Type: `boolean` Description: Whether the carousel is auto playing **`isDragging`** Type: `boolean` Description: Whether the carousel is being dragged. This only works when `draggable` is true. **`canScrollNext`** Type: `boolean` Description: Whether the carousel is can scroll to the next view **`canScrollPrev`** Type: `boolean` Description: Whether the carousel is can scroll to the previous view **`scrollToIndex`** Type: `(index: number, instant?: boolean) => void` Description: Function to scroll to a specific item index **`scrollTo`** Type: `(page: number, instant?: boolean) => void` Description: Function to scroll to a specific page **`scrollNext`** Type: `(instant?: boolean) => void` Description: Function to scroll to the next page **`scrollPrev`** Type: `(instant?: boolean) => void` Description: Function to scroll to the previous page **`getProgress`** Type: `() => number` Description: Returns the current scroll progress as a percentage **`getProgressText`** Type: `() => string` Description: Returns the progress text **`play`** Type: `VoidFunction` Description: Function to start/resume autoplay **`pause`** Type: `VoidFunction` Description: Function to pause autoplay **`isInView`** Type: `(index: number) => boolean` Description: Whether the item is in view **`refresh`** Type: `VoidFunction` Description: Function to re-compute the snap points and clamp the page ### Data Attributes **`Root`** **`data-scope`**: carousel **`data-part`**: root **`data-orientation`**: The orientation of the carousel **`ItemGroup`** **`data-scope`**: carousel **`data-part`**: item-group **`data-orientation`**: The orientation of the item **`data-dragging`**: Present when in the dragging state **`Item`** **`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 **`Control`** **`data-scope`**: carousel **`data-part`**: control **`data-orientation`**: The orientation of the control **`PrevTrigger`** **`data-scope`**: carousel **`data-part`**: prev-trigger **`data-orientation`**: The orientation of the prevtrigger **`NextTrigger`** **`data-scope`**: carousel **`data-part`**: next-trigger **`data-orientation`**: The orientation of the nexttrigger **`IndicatorGroup`** **`data-scope`**: carousel **`data-part`**: indicator-group **`data-orientation`**: The orientation of the indicatorgroup **`Indicator`** **`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 **`AutoplayTrigger`** **`data-scope`**: carousel **`data-part`**: autoplay-trigger **`data-orientation`**: The orientation of the autoplaytrigger **`data-pressed`**: Present when pressed ### CSS Variables A cascade select component allows users to select from hierarchical data through multiple linked levels of dropdown menus. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/cascade-select) [Logic Visualizer](https://zag-visualizer.vercel.app/cascade-select) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/cascade-select) **Features** - Supports hierarchical data with unlimited depth levels - Full keyboard navigation across all levels with arrow keys - Supports single and multiple selections - Supports both click and hover triggering modes - Supports looping keyboard navigation - Built-in accessibility with ARIA roles and keyboard interactions - Supports disabled items and read-only state - Form integration with hidden input element - Supports right-to-left direction ## Installation Install the cascade select package: ```bash npm install @zag-js/cascade-select @zag-js/vue # or yarn add @zag-js/cascade-select @zag-js/vue ``` ## Anatomy Check the cascade select anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the cascade select package: ```jsx import * as cascadeSelect from "@zag-js/cascade-select" ``` These are the key exports: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. - `collection` - Creates a tree collection from your hierarchical data. ### Create the collection Use the `collection` function to create a tree collection from your hierarchical data. Pass a `rootNode` along with functions to extract each node's value, string label, and children. ```ts import * as cascadeSelect from "@zag-js/cascade-select" interface Node { label: string value: string children?: Node[] } const collection = cascadeSelect.collection({ nodeToValue: (node) => node.value, nodeToString: (node) => node.label, nodeToChildren: (node) => node.children, rootNode: { label: "ROOT", value: "ROOT", children: [ { label: "North America", value: "north-america", children: [ { label: "United States", value: "us", children: [ { label: "New York", value: "ny" }, { label: "California", value: "ca" }, ], }, { label: "Canada", value: "canada" }, ], }, { label: "Africa", value: "africa", children: [ { label: "Nigeria", value: "ng" }, { label: "Kenya", value: "ke" }, ], }, ], }, }) ``` ### Create the cascade select > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ```html ``` ### Setting the initial value Use the `defaultValue` property to set the initial value of the cascade select. > The `value` property must be an array of string paths. Each path is an array > of values from the root to the selected leaf item. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, defaultValue: [["north-america", "us", "ny"]], }) ``` ### Controlled selection Use `value` and `onValueChange` for controlled selection state. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, value, onValueChange(details) { setValue(details.value) }, }) ``` ### Selecting multiple values To allow selecting multiple values, set the `multiple` property to `true`. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, multiple: true, }) ``` ### Hover triggering By default, items are highlighted when clicked. To highlight items on hover instead (like a traditional cascading menu), set the `highlightTrigger` property to `"hover"`. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, highlightTrigger: "hover", }) ``` ### Allowing parent selection By default, only leaf nodes (items without children) can be selected. To allow parent (branch) nodes to also be selectable, set `allowParentSelection` to `true`. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, allowParentSelection: true, }) ``` ### Close on select By default, the menu closes when you select an item. Set `closeOnSelect` to `false` to keep it open. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, closeOnSelect: false, }) ``` ### Looping the keyboard navigation By default, arrow-key navigation stops at the first and last items. Set `loopFocus: true` to loop back around. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, loopFocus: true, }) ``` ### Listening for highlight changes When an item is highlighted with the pointer or keyboard, use the `onHighlightChange` to listen for the change and do something with it. ```jsx {3-6} const service = useMachine(cascadeSelect.machine, { id: useId(), onHighlightChange(details) { // details => { highlightedValue: string[], highlightedItems: Item[] } console.log(details) }, }) ``` ### Setting the initial highlighted path Use `defaultHighlightedValue` to set the initially highlighted path. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, defaultHighlightedValue: ["north-america", "us"], }) ``` ### Controlled highlighted path Use `highlightedValue` and `onHighlightChange` to control highlighting externally. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, highlightedValue, onHighlightChange(details) { setHighlightedValue(details.highlightedValue) }, }) ``` ### Listening for selection changes When an item is selected, use the `onValueChange` property to listen for the change and do something with it. ```jsx {4-7} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, onValueChange(details) { // details => { value: string[][], items: Item[][] } console.log(details) }, }) ``` ### Listening for open and close events Use `onOpenChange` to listen for open and close events. ```jsx {4-7} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, onOpenChange(details) { // details => { open: boolean, value: string[][] } console.log(details) }, }) ``` ### Controlling open state Use `open` and `onOpenChange` for controlled open state, or `defaultOpen` for an uncontrolled initial state. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, open, onOpenChange({ open }) { setOpen(open) }, }) ``` ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, defaultOpen: true, }) ``` ### Positioning submenu panels Use `positioning` to configure placement and collision behavior. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, positioning: { placement: "right-start", gutter: 4, }, }) ``` ### Custom scroll behavior Use `scrollToIndexFn` to customize how each level scrolls highlighted items into view. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, scrollToIndexFn(details) { // details => { index, depth, immediate? } customScroll(details) }, }) ``` ### Customizing the trigger label Use `formatValue` to control how selected paths are rendered in the trigger. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, formatValue(selectedItems) { return selectedItems .map((path) => path.map((item) => item.label).join(" / ")) .join(", ") }, }) ``` ### Usage within a form To use cascade select in a form, pass `name`. A hidden input is rendered with `getHiddenInputProps()`. ```jsx {4} const service = useMachine(cascadeSelect.machine, { id: useId(), collection, name: "location", }) // In your JSX ``` If the hidden input belongs to a different form element, also set `form`. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, name: "location", form: "checkout-form", }) ``` ### Validation and read-only state Use `readOnly`, `required`, and `invalid` to control interaction and form state. ```jsx const service = useMachine(cascadeSelect.machine, { id: useId(), collection, readOnly: true, required: true, invalid: false, }) ``` ## Styling guide Each cascade select part includes a `data-part` attribute you can target in CSS. ### Open and closed state When the cascade select is open, the trigger and content is given a `data-state` attribute. ```css [data-part="trigger"][data-state="open|closed"] { /* styles for open or closed state */ } [data-part="content"][data-state="open|closed"] { /* styles for open or closed state */ } ``` ### Selected state Items are given a `data-state` attribute, indicating whether they are selected. ```css [data-part="item"][data-state="checked|unchecked"] { /* styles for selected or unselected state */ } ``` ### Highlighted state When an item is highlighted, via keyboard navigation or pointer, it is given a `data-highlighted` attribute. ```css [data-part="item"][data-highlighted] { /* styles for highlighted state */ } ``` ### Branch items When an item has children (is a branch node), it is given a `data-has-children` attribute. ```css [data-part="item"][data-has-children] { /* styles for items with children (branch nodes) */ } ``` ### Invalid state When the cascade select is invalid, the label and trigger is given a `data-invalid` attribute. ```css [data-part="label"][data-invalid] { /* styles for invalid state */ } [data-part="trigger"][data-invalid] { /* styles for invalid state */ } ``` ### Disabled state When the cascade select is disabled, the trigger and label is given a `data-disabled` attribute. ```css [data-part="trigger"][data-disabled] { /* styles for disabled state */ } [data-part="label"][data-disabled] { /* styles for disabled label state */ } [data-part="item"][data-disabled] { /* styles for disabled item state */ } ``` ### Empty state When no option is selected, the trigger is given a `data-placeholder-shown` attribute. ```css [data-part="trigger"][data-placeholder-shown] { /* styles for empty state */ } ``` ## Methods and Properties ### Machine Context The cascade select machine exposes the following context properties: **`collection`** Type: `TreeCollection` Description: The tree collection data **`ids`** Type: `Partial<{ root: string; label: string; control: string; trigger: string; indicator: string; clearTrigger: string; positioner: string; content: string; hiddenInput: string; list(valuePath: string): string; item(valuePath: string): string; }>` Description: The ids of the cascade-select elements. Useful for composition. **`name`** Type: `string` Description: The name attribute of the underlying input element **`form`** Type: `string` Description: The form attribute of the underlying input element **`value`** Type: `string[][]` Description: The controlled value of the cascade-select **`defaultValue`** Type: `string[][]` Description: The initial value of the cascade-select when rendered. Use when you don't need to control the value. **`highlightedValue`** Type: `string[]` Description: The controlled highlighted value of the cascade-select **`defaultHighlightedValue`** Type: `string[]` Description: The initial highlighted value of the cascade-select when rendered. **`multiple`** Type: `boolean` Description: Whether to allow multiple selections **`open`** Type: `boolean` Description: The controlled open state of the cascade-select **`defaultOpen`** Type: `boolean` Description: The initial open state of the cascade-select when rendered. Use when you don't need to control the open state. **`highlightTrigger`** Type: `"click" | "hover"` Description: What triggers highlighting of items **`closeOnSelect`** Type: `boolean` Description: Whether the cascade-select should close when an item is selected **`loopFocus`** Type: `boolean` Description: Whether the cascade-select should loop focus when navigating with keyboard **`disabled`** Type: `boolean` Description: Whether the cascade-select is disabled **`readOnly`** Type: `boolean` Description: Whether the cascade-select is read-only **`required`** Type: `boolean` Description: Whether the cascade-select is required **`invalid`** Type: `boolean` Description: Whether the cascade-select is invalid **`positioning`** Type: `PositioningOptions` Description: The positioning options for the cascade-select content **`scrollToIndexFn`** Type: `(details: ScrollToIndexDetails) => void` Description: Function to scroll to a specific index in a list **`formatValue`** Type: `(selectedItems: T[][]) => string` Description: Function to format the display value **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: Called when the value changes **`onHighlightChange`** Type: `(details: HighlightChangeDetails) => void` Description: Called when the highlighted value changes **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: Called when the open state changes **`allowParentSelection`** Type: `boolean` Description: Whether parent (branch) items can be selectable **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`onPointerDownOutside`** Type: `(event: PointerDownOutsideEvent) => void` Description: Function called when the pointer is pressed down outside the component **`onFocusOutside`** Type: `(event: FocusOutsideEvent) => void` Description: Function called when the focus is moved outside the component **`onInteractOutside`** Type: `(event: InteractOutsideEvent) => void` Description: Function called when an interaction happens outside the component ### Machine API The cascade select `api` exposes the following methods: **`collection`** Type: `TreeCollection` Description: The tree collection data **`open`** Type: `boolean` Description: Whether the cascade-select is open **`focused`** Type: `boolean` Description: Whether the cascade-select is focused **`multiple`** Type: `boolean` Description: Whether the cascade-select allows multiple selections **`disabled`** Type: `boolean` Description: Whether the cascade-select is disabled **`highlightedValue`** Type: `string[]` Description: The value of the highlighted item **`highlightedItems`** Type: `V[]` Description: The items along the highlighted path **`selectedItems`** Type: `V[][]` Description: The selected items **`hasSelectedItems`** Type: `boolean` Description: Whether there's a selected option **`empty`** Type: `boolean` Description: Whether the cascade-select value is empty **`value`** Type: `string[][]` Description: The current value of the cascade-select **`valueAsString`** Type: `string` Description: The current value as text **`focus`** Type: `() => void` Description: Function to focus on the select input **`reposition`** Type: `(options?: Partial) => void` Description: Function to set the positioning options of the cascade-select **`setOpen`** Type: `(open: boolean) => void` Description: Function to open the cascade-select **`setHighlightValue`** Type: `(value: string | string[]) => void` Description: Function to set the highlighted value (path or single value to find) **`clearHighlightValue`** Type: `() => void` Description: Function to clear the highlighted value **`selectValue`** Type: `(value: string[]) => void` Description: Function to select a value **`setValue`** Type: `(value: string[][]) => void` Description: Function to set the value **`clearValue`** Type: `(value?: string[]) => void` Description: Function to clear the value **`getItemState`** Type: `(props: ItemProps) => ItemState` Description: Returns the state of a cascade-select item ### Data Attributes **`Root`** **`data-scope`**: cascade-select **`data-part`**: root **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`data-state`**: "open" | "closed" **`Label`** **`data-scope`**: cascade-select **`data-part`**: label **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`Control`** **`data-scope`**: cascade-select **`data-part`**: control **`data-disabled`**: Present when disabled **`data-focus`**: Present when focused **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`data-state`**: "open" | "closed" **`Trigger`** **`data-scope`**: cascade-select **`data-part`**: trigger **`data-state`**: "open" | "closed" **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`data-focus`**: Present when focused **`data-placement`**: The placement of the trigger **`data-placeholder-shown`**: Present when placeholder is shown **`ClearTrigger`** **`data-scope`**: cascade-select **`data-part`**: clear-trigger **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`Content`** **`data-scope`**: cascade-select **`data-part`**: content **`data-activedescendant`**: The id the active descendant of the content **`data-state`**: "open" | "closed" **`List`** **`data-scope`**: cascade-select **`data-part`**: list **`data-depth`**: The depth of the item **`Indicator`** **`data-scope`**: cascade-select **`data-part`**: indicator **`data-state`**: "open" | "closed" **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`Item`** **`data-scope`**: cascade-select **`data-part`**: item **`data-value`**: The value of the item **`data-disabled`**: Present when disabled **`data-highlighted`**: Present when highlighted **`data-selected`**: Present when selected **`data-depth`**: The depth of the item **`data-state`**: "checked" | "unchecked" **`data-type`**: The type of the item **`data-index-path`**: **`ItemText`** **`data-scope`**: cascade-select **`data-part`**: item-text **`data-value`**: The value of the item **`data-highlighted`**: Present when highlighted **`data-state`**: "checked" | "unchecked" **`data-disabled`**: Present when disabled **`ItemIndicator`** **`data-scope`**: cascade-select **`data-part`**: item-indicator **`data-value`**: The value of the item **`data-highlighted`**: Present when highlighted **`data-type`**: The type of the item **`data-state`**: "checked" | "unchecked" **`ValueText`** **`data-scope`**: cascade-select **`data-part`**: value-text **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-focus`**: Present when focused ### CSS Variables ## Accessibility Adheres to the [ListBox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox). ### Keyboard Interactions **`Space`** Description: When focus is on trigger, opens the cascade select and focuses the first item.
When focus is on the content, selects the highlighted item.
**`Enter`** Description: When focus is on trigger, opens the cascade select and focuses the first item.
When focus is on content, selects the highlighted item.
**`ArrowDown`** Description: When focus is on trigger, opens the cascade select.
When focus is on content, moves focus to the next item in the current level.
**`ArrowUp`** Description: When focus is on trigger, opens the cascade select and focuses the last item.
When focus is on content, moves focus to the previous item in the current level.
**`ArrowRight`** Description: When focus is on a branch item, expands the next level and moves focus into it. **`ArrowLeft`** Description: When focus is on a nested level, collapses it and moves focus back to the parent.
When focus is at the root level, closes the cascade select.
**`Home`** Description: Moves focus to the first item in the current level. **`End`** Description: Moves focus to the last item in the current level. **`Esc`** Description: Closes the cascade select and moves focus to trigger. A checkbox allows users to make a binary choice, i.e. a choice between one of two possible mutually exclusive options. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/checkbox) [Logic Visualizer](https://zag-visualizer.vercel.app/checkbox) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/checkbox) **Features** - Tri-state checkbox (`indeterminate` state) - Syncs with `disabled` state of fieldset - Syncs with form `reset` events - Can be toggled programmatically ## Installation Install the checkbox package: ```bash npm install @zag-js/checkbox @zag-js/vue # or yarn add @zag-js/checkbox @zag-js/vue ``` ## Anatomy Check the checkbox anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the checkbox package: ```jsx import * as checkbox from "@zag-js/checkbox" ``` The checkbox package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. Then use the framework integration helpers: ```html ``` ### Setting the initial checked state Set `defaultChecked` to `true` to start checked. ```jsx {2} const service = useMachine(checkbox.machine, { defaultChecked: true, }) ``` ### Indeterminate checkboxes Set `defaultChecked` or `checked` to `"indeterminate"` for a tri-state checkbox. ```jsx {2} const service = useMachine(checkbox.machine, { defaultChecked: "indeterminate", }) ``` ### Controlled checkbox Use `checked` and `onCheckedChange` to control state externally. ```html ``` ### Disabling the checkbox Set `disabled` to `true` to prevent interaction. ```jsx {2} const service = useMachine(checkbox.machine, { disabled: true, }) ``` ### Listening for changes When the checked state changes, `onCheckedChange` is invoked. ```jsx {2-5} const service = useMachine(checkbox.machine, { onCheckedChange(details) { // details => { checked: boolean | "indeterminate" } console.log("checkbox is:", details.checked) }, }) ``` ### Read-only checkbox Set `readOnly` to keep the checkbox focusable but prevent toggling. ```jsx {2} const service = useMachine(checkbox.machine, { readOnly: true, }) ``` ### Usage within forms To use checkbox within forms, set `name` and render `api.getHiddenInputProps()`. ```jsx {2} const service = useMachine(checkbox.machine, { name: "fruits", }) ``` Next, render the hidden input and ensure the value changes get propagated to the form correctly. ```jsx ``` ### Customizing submitted value Set `value` to customize the submitted form value when checked. ```jsx const service = useMachine(checkbox.machine, { name: "newsletter", value: "subscribed", }) ``` ### Associating with an external form If the input belongs to a different form element, set `form`. ```jsx const service = useMachine(checkbox.machine, { name: "newsletter", form: "settings-form", }) ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ### Checked state When the checkbox input is checked, the `data-state` attribute is added to the root, control and label parts. ```css [data-part="root"][data-state="checked|unchecked|indeterminate"] { /* styles for when checkbox is checked */ } [data-part="control"][data-state="checked|unchecked|indeterminate"] { /* styles for when checkbox is checked */ } [data-part="label"][data-state="checked|unchecked|indeterminate"] { /* styles for when checkbox is checked */ } ``` ### Focused State When the checkbox input is focused, the `data-focus` attribute is added to the root, control and label parts. ```css [data-part="root"][data-focus] { /* styles for root focus state */ } [data-part="control"][data-focus] { /* styles for control focus state */ } [data-part="label"][data-focus] { /* styles for label focus state */ } ``` ### Disabled State When the checkbox is disabled, the `data-disabled` attribute is added to the root, control and label parts. ```css [data-part="root"][data-disabled] { /* styles for root disabled state */ } [data-part="control"][data-disabled] { /* styles for control disabled state */ } [data-part="label"][data-disabled] { /* styles for label disabled state */ } ``` ### Invalid State When the checkbox is invalid, the `data-invalid` attribute is added to the root, control and label parts. ```css [data-part="root"][data-invalid] { /* styles for root invalid state */ } [data-part="control"][data-invalid] { /* styles for control invalid state */ } [data-part="label"][data-invalid] { /* styles for label invalid state */ } ``` ## Methods and Properties ### Machine Context The checkbox machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; hiddenInput: string; control: string; label: string; }>` Description: The ids of the elements in the checkbox. Useful for composition. **`disabled`** Type: `boolean` Description: Whether the checkbox is disabled **`invalid`** Type: `boolean` Description: Whether the checkbox is invalid **`required`** Type: `boolean` Description: Whether the checkbox is required **`checked`** Type: `CheckedState` Description: The controlled checked state of the checkbox **`defaultChecked`** Type: `CheckedState` Description: The initial checked state of the checkbox when rendered. Use when you don't need to control the checked state of the checkbox. **`readOnly`** Type: `boolean` Description: Whether the checkbox is read-only **`onCheckedChange`** Type: `(details: CheckedChangeDetails) => void` Description: The callback invoked when the checked state changes. **`name`** Type: `string` Description: The name of the input field in a checkbox. Useful for form submission. **`form`** Type: `string` Description: The id of the form that the checkbox belongs to. **`value`** Type: `string` Description: The value of checkbox input. Useful for form submission. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. ### Machine API The checkbox `api` exposes the following methods: **`checked`** Type: `boolean` Description: Whether the checkbox is checked **`disabled`** Type: `boolean` Description: Whether the checkbox is disabled **`indeterminate`** Type: `boolean` Description: Whether the checkbox is indeterminate **`focused`** Type: `boolean` Description: Whether the checkbox is focused **`checkedState`** Type: `CheckedState` Description: The checked state of the checkbox **`setChecked`** Type: `(checked: CheckedState) => void` Description: Function to set the checked state of the checkbox **`toggleChecked`** Type: `VoidFunction` Description: Function to toggle the checked state of the checkbox ### Data Attributes **`Root`** **`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`** **`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`** **`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 **`Indicator`** **`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 ## Accessibility ### Keyboard Interactions **`Space`** Description: Toggle the checkbox The clipboard machine lets users quickly copy content to the clipboard. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/clipboard) [Logic Visualizer](https://zag-visualizer.vercel.app/clipboard) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/clipboard) ## Installation Install the clipboard package: ```bash npm install @zag-js/clipboard @zag-js/vue # or yarn add @zag-js/clipboard @zag-js/vue ``` ## Anatomy Check the clipboard anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the clipboard package: ```jsx import * as clipboard from "@zag-js/clipboard" ``` The clipboard package exports two key functions: - `machine` - State machine logic. - `connect` - Maps machine state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Setting the clipboard value Set `value` to control what gets copied. ```jsx {2} const service = useMachine(clipboard.machine, { value: "Hello, world!", }) ``` ### Setting an initial value Use `defaultValue` for uncontrolled initial value. ```jsx const service = useMachine(clipboard.machine, { defaultValue: "Hello, world!", }) ``` ### Listening for value changes Use `onValueChange` to react when the clipboard value changes. ```jsx const service = useMachine(clipboard.machine, { onValueChange(details) { console.log("Value changed to", details.value) }, }) ``` ### Listening to copy events When the value is copied, `onStatusChange` is fired. ```jsx {2} const service = useMachine(clipboard.machine, { onStatusChange: (details) => { console.log("Copy status changed to", details.copied) }, }) ``` ### Checking if the value is copied Use `api.copied` to check if the value was copied. ```jsx {2} const api = clipboard.connect(service) if (api.copied) { console.log("Value is copied to the clipboard") } ``` ### Changing the timeout By default, the copied feedback resets after `3000ms`. Set `timeout` to change this delay. ```jsx {2} const service = useMachine(clipboard.machine, { timeout: 5000, }) ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ```css [data-scope="clipboard"][data-part="root"] { /* styles for the root part */ } ``` ## Methods and Properties ### Machine Context The clipboard machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; input: string; label: string; }>` Description: The ids of the elements in the clipboard. Useful for composition. **`value`** Type: `string` Description: The controlled value of the clipboard **`defaultValue`** Type: `string` Description: The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard. **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: The function to be called when the value changes **`onStatusChange`** Type: `(details: CopyStatusDetails) => void` Description: The function to be called when the value is copied to the clipboard **`timeout`** Type: `number` Description: The timeout for the copy operation **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. ### Machine API The clipboard `api` exposes the following methods: **`copied`** Type: `boolean` Description: Whether the value has been copied to the clipboard **`value`** Type: `string` Description: The value to be copied to the clipboard **`setValue`** Type: `(value: string) => void` Description: Set the value to be copied to the clipboard **`copy`** Type: `VoidFunction` Description: Copy the value to the clipboard ### Data Attributes **`Root`** **`data-scope`**: clipboard **`data-part`**: root **`data-copied`**: Present when copied state is true **`Label`** **`data-scope`**: clipboard **`data-part`**: label **`data-copied`**: Present when copied state is true **`Control`** **`data-scope`**: clipboard **`data-part`**: control **`data-copied`**: Present when copied state is true **`Input`** **`data-scope`**: clipboard **`data-part`**: input **`data-copied`**: Present when copied state is true **`data-readonly`**: Present when read-only **`Trigger`** **`data-scope`**: clipboard **`data-part`**: trigger **`data-copied`**: Present when copied state is true A collapsible is a component which expands and collapses a panel. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/collapsible) [Logic Visualizer](https://zag-visualizer.vercel.app/collapsible) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/collapsible) **Features** - Can be controlled or uncontrolled - Works for width and height collapsibles ## Installation Install the collapsible package: ```bash npm install @zag-js/collapsible @zag-js/vue # or yarn add @zag-js/collapsible @zag-js/vue ``` ## Usage Import the collapsible package: ```jsx import * as collapsible from "@zag-js/collapsible" ``` The collapsible package exports two key functions: - `machine` - State logic for the collapsible. - `connect` - Maps state to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Setting the initial state Set `defaultOpen` to control the initial open state. ```jsx const service = useMachine(collapsible.machine, { defaultOpen: true, }) ``` ### Controlled collapsible Use `open` and `onOpenChange` to control the open state externally. ```html ``` ### Listening for changes When the collapsible state changes, the `onOpenChange` callback is invoked. ```jsx {2-5} const service = useMachine(collapsible.machine, { onOpenChange(details) { // details => { open: boolean } console.log("collapsible open:", details.open) }, }) ``` ### Disabling the collapsible Set `disabled` to `true` to disable interaction. ```jsx {2} const service = useMachine(collapsible.machine, { disabled: true, }) ``` ### Partial collapse (setting minimum dimensions) Use `collapsedHeight` or `collapsedWidth` to create a "partially collapsed" state. When collapsed, the content keeps the specified minimum size instead of collapsing to `0px`. ```jsx {3} const service = useMachine(collapsible.machine, { // Content shows 100px height when collapsed collapsedHeight: "100px", }) ``` This is useful for creating "show more/less" content sections or preview states where a portion of the content shows even when collapsed. ### Running code after close animation Use `onExitComplete` to run code when the close animation finishes. ```jsx const service = useMachine(collapsible.machine, { onExitComplete() { console.log("Collapsible is fully closed") }, }) ``` ### Animating the collapsible Use CSS animations to animate the collapsible when it expands and collapses. The `--height` and `--width` custom properties are attached to the content part. ```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"] { overflow: hidden; max-width: 400px; } [data-scope="collapsible"][data-part="content"][data-state="open"] { animation: expand 110ms cubic-bezier(0, 0, 0.38, 0.9); } [data-scope="collapsible"][data-part="content"][data-state="closed"] { animation: collapse 110ms cubic-bezier(0, 0, 0.38, 0.9); } ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ### Open and closed state When a collapsible opens or closes, `data-state` is set to `open` or `closed` on the root, trigger, and content. ```css [data-part="root"][data-state="open|closed"] { /* styles for the collapsible is open or closed state */ } [data-part="trigger"][data-state="open|closed"] { /* styles for the collapsible is open or closed state */ } [data-part="content"][data-state="open|closed"] { /* styles for the collapsible is open or closed state */ } ``` ### Focused state When a collapsible's trigger is focused, a `data-focus` attribute is set on the root, trigger and content. ```css [data-part="root"][data-focus] { /* styles for the item's focus state */ } [data-part="trigger"][data-focus] { /* styles for the content's focus state */ } [data-part="content"][data-focus] { /* styles for the content's focus state */ } ``` ### Collapse animation The collapsible content provides `--width`, `--height`, `--collapsed-width`, and `--collapsed-height` CSS variables that can be used to create smooth animations. These variables are automatically calculated and updated based on the content's dimensions. ```css [data-scope="collapsible"][data-part="content"][data-state="open"] { animation: slideDown 200ms ease; } [data-scope="collapsible"][data-part="content"][data-state="closed"] { animation: slideUp 200ms ease; } @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; } } ``` ## Methods and Properties The collapsible's `api` exposes the following methods and properties: ### Machine Context The collapsible machine exposes the following context properties: **`ids`** Type: `Partial<{ root: string; content: string; trigger: string; }>` Description: The ids of the elements in the collapsible. Useful for composition. **`open`** Type: `boolean` Description: The controlled open state of the collapsible. **`defaultOpen`** Type: `boolean` Description: The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: The callback invoked when the open state changes. **`onExitComplete`** Type: `VoidFunction` Description: The callback invoked when the exit animation completes. **`disabled`** Type: `boolean` Description: Whether the collapsible is disabled. **`collapsedHeight`** Type: `string | number` Description: The height of the content when collapsed. **`collapsedWidth`** Type: `string | number` Description: The width of the content when collapsed. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. ### Machine API The collapsible `api` exposes the following methods: **`open`** Type: `boolean` Description: Whether the collapsible is open. **`visible`** Type: `boolean` Description: Whether the collapsible is visible (open or closing) **`disabled`** Type: `boolean` Description: Whether the collapsible is disabled **`setOpen`** Type: `(open: boolean) => void` Description: Function to open or close the collapsible. **`measureSize`** Type: `VoidFunction` Description: Function to measure the size of the content. ### Data Attributes **`Root`** **`data-scope`**: collapsible **`data-part`**: root **`data-state`**: "open" | "closed" **`Content`** **`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 **`Trigger`** **`data-scope`**: collapsible **`data-part`**: trigger **`data-state`**: "open" | "closed" **`data-disabled`**: Present when disabled **`Indicator`** **`data-scope`**: collapsible **`data-part`**: indicator **`data-state`**: "open" | "closed" **`data-disabled`**: Present when disabled ### CSS Variables ## Accessibility Adheres to the [Disclosure WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure). ### Keyboard Interactions **`Space`** Description: Opens/closes the collapsible. **`Enter`** Description: Opens/closes the collapsible. The color picker is an input widget used to select a color value from a predefined list or a color area. This component builds on top of the native `` experience and provides a more customizable and consistent user experience. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/color-picker) [Logic Visualizer](https://zag-visualizer.vercel.app/color-picker) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/color-picker) **Features** - Supports custom color area - Supports RGBA, HSLA, HEX, and HSBA formats - Supports channel inputs and sliders - Supports mouse, touch, and keyboard interactions - Supports form submission and reset events - Supports named CSS colors ## Installation Install the color picker package: ```bash npm install @zag-js/color-picker @zag-js/vue # or yarn add @zag-js/color-picker @zag-js/vue ``` ## Anatomy To set up the color picker correctly, you'll need to understand its anatomy and how we name its parts. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the color picker package: ```jsx import * as colorPicker from "@zag-js/color-picker" ``` These are the key exports: - `machine` - Behavior logic for the color picker. - `connect` - Maps state to JSX props and event handlers. - `parse` - Parses a color string into a `Color` object. Then use the framework integration helpers: ```html ``` ### Setting the initial color Set `defaultValue` to define the initial color. ```jsx const [current, send] = useMachine(colorPicker.machine, { defaultValue: colorPicker.parse("#ff0000"), }) ``` ### Controlled color picker Use `value` and `onValueChange` to control color externally. > **Note:** We recommend preserving the value as a `Color` object rather than a > string to prevent calculation errors by converting back and forth. ```html ``` ### Listening for change events When the user selects a color using the color picker, the `onValueChange` and `onValueChangeEnd` events will be fired. - `onValueChange` — Fires in sync as the user selects a color - `onValueChangeEnd` — Fires when the user stops selecting a color (useful for debounced updates) ```jsx const [current, send] = useMachine(colorPicker.machine, { onValueChange: (details) => { // details => { value: Color, valueAsString: string } }, onValueChangeEnd: (details) => { // details => { value: Color, valueAsString: string } }, }) ``` ### Using a custom color format By default, the color picker's output format is `rgba`. You can change this format to either `hsla` or `hsba` with `format`. When this is set, the `value` and `valueAsString` properties of the `onValueChange` event will be updated to reflect the new format. ```jsx const [current, send] = useMachine(colorPicker.machine, { format: "hsla", onValueChange: (details) => { // details => { value: HSLAColor, valueAsString: string } }, }) ``` ### Setting the initial format Use `defaultFormat` to set the initial output format. ```jsx const [current, send] = useMachine(colorPicker.machine, { defaultFormat: "hsla", }) ``` ### Controlled format Use `format` and `onFormatChange` to control the active format. ```jsx const [current, send] = useMachine(colorPicker.machine, { format, onFormatChange(details) { setFormat(details.format) }, }) ``` ### Showing color presets Adding color presets as swatches can help users pick colors faster. To support this, use the `getSwatchTriggerProps(...)` and `getSwatchProps(...)` to get the props needed to render swatch buttons. ```html ``` ### Closing after swatch selection Set `closeOnSelect` to close the popup when a swatch is selected. ```jsx const [current, send] = useMachine(colorPicker.machine, { closeOnSelect: true, }) ``` ### Disabling the color picker Set `disabled` to `true` to disable user interaction. ```jsx const [current, send] = useMachine(colorPicker.machine, { disabled: true, }) ``` ### Controlling the open and closed state Use `open` and `onOpenChange` to control whether the picker is visible. ```jsx const [current, send] = useMachine(colorPicker.machine, { open: true, onOpenChange: (details) => { // details => { open: boolean, value: Color } }, }) ``` You can also leverage the `api.setOpen(...)` method to control the open and closed state of the color picker. ### Positioning the popup Use `positioning` to control popup placement and collision behavior. ```jsx const [current, send] = useMachine(colorPicker.machine, { positioning: { placement: "bottom-start", gutter: 8 }, }) ``` ### Setting initial focus when opened Use `initialFocusEl` to choose which element receives focus when the popup opens. ```jsx const [current, send] = useMachine(colorPicker.machine, { initialFocusEl: () => document.getElementById("alpha-input"), }) ``` ### Inline rendering Set `inline` to render the picker without a trigger and popup. ```jsx const [current, send] = useMachine(colorPicker.machine, { inline: true, }) ``` ### Controlling individual color channel In some cases, you may want to allow users to control the values of each color channel individually. You can do this using an input element or a slider element, or both. To support this, use the `getChannelInputProps(...)` to show the channel inputs. > Note: Make sure you only render the channel inputs that match the `format` of > the color picker. ```html ``` ### Showing a color preview To display the value of a color, use the `getSwatchProps(...)` and pass the color value. To show the current color value, use `api.value`. ```html ``` > You can pass `respectAlpha: false` to show the color value without the alpha > channel ### Adding an eyedropper The eye dropper tool is a native browser feature that lets users pick a color from a current page's canvas. To support this, use the `getEyeDropperTriggerProps(...)`. > **Note:** The eye dropper tool only works in Chrome and Edge browsers ```html ``` ### Usage within forms To use the color picker in a form, set `name` and render the hidden input. ```jsx {2} const service = useMachine(colorPicker.machine, { name: "color-preference", }) ``` ## Styling guide Each color picker part has a `data-part` attribute added to them to help you identify and style them easily. ### Open and closed state When the color picker is open or closed, the `data-state` attribute is added to the trigger, content, control parts. ```css [data-part="control"][data-state="open|closed"] { /* styles for control open or state */ } [data-part="trigger"][data-state="open|closed"] { /* styles for control open or state */ } [data-part="content"][data-state="open|closed"] { /* styles for control open or state */ } ``` ### Focused State When the color picker is focused, the `data-focus` attribute is added to the control and label parts. ```css [data-part="control"][data-focus] { /* styles for control focus state */ } [data-part="label"][data-focus] { /* styles for label focus state */ } ``` ### Disabled State When the color picker is disabled, the `data-disabled` attribute is added to the label, control, trigger and option parts. ```css [data-part="label"][data-disabled] { /* styles for label disabled state */ } [data-part="control"][data-disabled] { /* styles for control disabled state */ } [data-part="trigger"][data-disabled] { /* styles for trigger disabled state */ } [data-part="swatch-trigger"][data-disabled] { /* styles for item disabled state */ } ``` ### Swatch State When a swatch's color value matches the color picker's value, the `data-state=checked` attribute is added to the swatch part. ```css [data-part="swatch-trigger"][data-state="checked|unchecked"] { /* styles for swatch's checked state */ } ``` ## Methods and Properties ### Machine Context The color picker machine exposes the following context properties: **`ids`** Type: `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; channelSliderThumb: (id: ColorChannel) => string; }>` Description: The ids of the elements in the color picker. Useful for composition. **`value`** Type: `Color` Description: The controlled color value of the color picker **`defaultValue`** Type: `Color` Description: The initial color value when rendered. Use when you don't need to control the color value of the color picker. **`disabled`** Type: `boolean` Description: Whether the color picker is disabled **`readOnly`** Type: `boolean` Description: Whether the color picker is read-only **`required`** Type: `boolean` Description: Whether the color picker is required **`invalid`** Type: `boolean` Description: Whether the color picker is invalid **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: Handler that is called when the value changes, as the user drags. **`onValueChangeEnd`** Type: `(details: ValueChangeDetails) => void` Description: Handler that is called when the user stops dragging. **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: Handler that is called when the user opens or closes the color picker. **`name`** Type: `string` Description: The name for the form input **`positioning`** Type: `PositioningOptions` Description: The positioning options for the color picker **`initialFocusEl`** Type: `() => HTMLElement` Description: The initial focus element when the color picker is opened. **`open`** Type: `boolean` Description: The controlled open state of the color picker **`defaultOpen`** Type: `boolean` Description: 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. **`format`** Type: `ColorFormat` Description: The controlled color format to use **`defaultFormat`** Type: `ColorFormat` Description: The initial color format when rendered. Use when you don't need to control the color format of the color picker. **`onFormatChange`** Type: `(details: FormatChangeDetails) => void` Description: Function called when the color format changes **`closeOnSelect`** Type: `boolean` Description: Whether to close the color picker when a swatch is selected **`openAutoFocus`** Type: `boolean` Description: Whether to auto focus the color picker when it is opened **`inline`** Type: `boolean` Description: Whether to render the color picker inline **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => Node | ShadowRoot | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`onPointerDownOutside`** Type: `(event: PointerDownOutsideEvent) => void` Description: Function called when the pointer is pressed down outside the component **`onFocusOutside`** Type: `(event: FocusOutsideEvent) => void` Description: Function called when the focus is moved outside the component **`onInteractOutside`** Type: `(event: InteractOutsideEvent) => void` Description: Function called when an interaction happens outside the component ### Machine API The color picker `api` exposes the following methods: **`dragging`** Type: `boolean` Description: Whether the color picker is being dragged **`open`** Type: `boolean` Description: Whether the color picker is open **`inline`** Type: `boolean` Description: Whether the color picker is rendered inline **`value`** Type: `Color` Description: The current color value (as a string) **`valueAsString`** Type: `string` Description: The current color value (as a Color object) **`setValue`** Type: `(value: string | Color) => void` Description: Function to set the color value **`getChannelValue`** Type: `(channel: ColorChannel) => string` Description: Function to set the color value **`getChannelValueText`** Type: `(channel: ColorChannel, locale: string) => string` Description: Function to get the formatted and localized value of a specific channel **`setChannelValue`** Type: `(channel: ColorChannel, value: number) => void` Description: Function to set the color value of a specific channel **`format`** Type: `ColorFormat` Description: The current color format **`setFormat`** Type: `(format: ColorFormat) => void` Description: Function to set the color format **`alpha`** Type: `number` Description: The alpha value of the color **`setAlpha`** Type: `(value: number) => void` Description: Function to set the color alpha **`setOpen`** Type: `(open: boolean) => void` Description: Function to open or close the color picker ### Data Attributes **`Root`** **`data-scope`**: color-picker **`data-part`**: root **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-invalid`**: Present when invalid **`Label`** **`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 **`Control`** **`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 **`Trigger`** **`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 **`Content`** **`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" **`ValueText`** **`data-scope`**: color-picker **`data-part`**: value-text **`data-disabled`**: Present when disabled **`data-focus`**: Present when focused **`Area`** **`data-scope`**: color-picker **`data-part`**: area **`data-invalid`**: Present when invalid **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`AreaBackground`** **`data-scope`**: color-picker **`data-part`**: area-background **`data-invalid`**: Present when invalid **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`AreaThumb`** **`data-scope`**: color-picker **`data-part`**: area-thumb **`data-disabled`**: Present when disabled **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`ChannelSlider`** **`data-scope`**: color-picker **`data-part`**: channel-slider **`data-channel`**: The color channel of the channelslider **`data-orientation`**: The orientation of the channelslider **`ChannelSliderTrack`** **`data-scope`**: color-picker **`data-part`**: channel-slider-track **`data-channel`**: The color channel of the channelslidertrack **`data-orientation`**: The orientation of the channelslidertrack **`ChannelSliderLabel`** **`data-scope`**: color-picker **`data-part`**: channel-slider-label **`data-channel`**: The color channel of the channelsliderlabel **`ChannelSliderValueText`** **`data-scope`**: color-picker **`data-part`**: channel-slider-value-text **`data-channel`**: The color channel of the channelslidervaluetext **`ChannelSliderThumb`** **`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 **`ChannelInput`** **`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 **`EyeDropperTrigger`** **`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 **`SwatchTrigger`** **`data-scope`**: color-picker **`data-part`**: swatch-trigger **`data-state`**: "checked" | "unchecked" **`data-value`**: The value of the item **`data-disabled`**: Present when disabled **`Swatch`** **`data-scope`**: color-picker **`data-part`**: swatch **`data-state`**: "checked" | "unchecked" **`data-value`**: The value of the item ### CSS Variables ## Accessibility ### Keyboard Interactions **`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 A combobox is an input with a popup that lets you select a value from a collection. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/combobox) [Logic Visualizer](https://zag-visualizer.vercel.app/combobox) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/combobox) **Features** - Supports selecting multiple values - Supports disabled options - Supports custom user input values - Supports mouse, touch, and keyboard interactions - Supports opening the combobox listbox with arrow keys, including automatically focusing the first or last item accordingly ## Installation Install the combobox package: ```bash npm install @zag-js/combobox @zag-js/vue # or yarn add @zag-js/combobox @zag-js/vue ``` ## Anatomy Check the combobox anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the combobox package: ```jsx import * as combobox from "@zag-js/combobox" ``` These are the key exports: - `machine` - Behavior logic. - `connect` - Maps behavior to JSX props and event handlers. - `collection` - Creates a [collection interface](/overview/collection) from an array of items. Then use the framework integration helpers: ```html ``` ### Setting the initial value Set `defaultValue` to define the initial combobox value. ```jsx {13} const collection = combobox.collection({ items: [ { label: "Nigeria", value: "ng" }, { label: "Ghana", value: "gh" }, { label: "Kenya", value: "ke" }, //... ], }) const service = useMachine(combobox.machine, { id: useId(), collection, defaultValue: ["ng"], }) ``` ### Controlled combobox Use `value` and `onValueChange` to control the value programmatically. ```html ``` ### Setting the initial input value Use `defaultInputValue` to prefill the input on first render. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, defaultInputValue: "Nig", }) ``` ### Controlling the input value Use `inputValue` and `onInputValueChange` when you want to filter options as you type. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, inputValue, onInputValueChange({ inputValue }) { setInputValue(inputValue) setOptions(filterItems(inputValue)) }, }) ``` ### Selecting multiple values Set `multiple` to `true` to allow selecting multiple values. ```jsx {4} const service = useMachine(combobox.machine, { id: useId(), collection, multiple: true, }) ``` ### Using a custom object format By default, the combobox collection expects an array of items with `label` and `value` properties. To use a custom object format, pass the `itemToString` and `itemToValue` properties to the collection function. - `itemToString` — A function that returns the string representation of an item. Used to compare items when filtering. - `itemToValue` — A function that returns the unique value of an item. - `itemToDisabled` — A function that returns the disabled state of an item. ```jsx const collection = combobox.collection({ // custom object format items: [ { id: 1, fruit: "Banana", available: true, quantity: 10 }, { id: 2, fruit: "Apple", available: false, quantity: 5 }, { id: 3, fruit: "Orange", available: true, quantity: 3 }, //... ], // convert item to string itemToString(item) { return item.fruit }, // convert item to value itemToValue(item) { return item.id }, // convert item to disabled state itemToDisabled(item) { return !item.available || item.quantity === 0 }, }) // use the collection const service = useMachine(combobox.machine, { id: useId(), collection, }) ``` ### Rendering the selected values outside the combobox By default, selected values are shown in the input. For multiple selection, it is often better to render selected values outside the combobox. To do that: - Set the `selectionBehavior` to `clear`, which clears the input value when an item is selected. - Set the `multiple` property to `true` to allow selecting multiple values. - Render the selected values outside the combobox. ```jsx {4-6} const service = useMachine(combobox.machine, { id: useId(), collection, selectionBehavior: "clear", multiple: true, }) ``` ### Disabling the combobox Set `disabled` to `true` to disable the combobox. ```jsx {2} const service = useMachine(combobox.machine, { disabled: true, }) ``` ### Disabling an option Pass `isItemDisabled` to disable specific options. ```jsx {6-8} const service = useMachine(combobox.machine, { id: useId(), collection: combobox.collection({ items: countries, isItemDisabled(item) { return item.disabled }, }), }) ``` ### Close on select By default, the menu closes when an option is selected with pointer or enter key. Set `closeOnSelect` to `false` to keep it open. ```jsx {2} const service = useMachine(combobox.machine, { closeOnSelect: false, }) ``` ### Controlling open state Use `open` and `onOpenChange` for controlled popup state, or `defaultOpen` for an uncontrolled initial state. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, open, onOpenChange(details) { // details => { open: boolean; reason?: string; value: string[] } setOpen(details.open) }, }) ``` ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, defaultOpen: true, }) ``` ### Configuring popup trigger behavior Use these props to fine-tune when the popup opens: - `openOnClick` to open when the input is clicked - `openOnChange` to control opening on input changes - `openOnKeyPress` to control opening on arrow key press - `inputBehavior` to set how typing and keyboard navigation affect highlight/input ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, openOnClick: true, openOnChange: false, openOnKeyPress: false, inputBehavior: "autohighlight", }) ``` ### Positioning the popup Use `positioning` to control how the popup is placed. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, positioning: { placement: "bottom-start" }, }) ``` ### Submitting forms on Enter Set `alwaysSubmitOnEnter` to `true` if you want Enter to submit the form even while the popup is open. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, alwaysSubmitOnEnter: true, }) ``` ### Making the combobox readonly Set `readOnly` to `true` to make the combobox read-only. ```jsx {2} const service = useMachine(combobox.machine, { readOnly: true, }) ``` ### Required and invalid state Set `required` and `invalid` for form validation and UI state. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, required: true, invalid: false, }) ``` ### Listening for highlight changes Use `onHighlightChange` to listen for highlighted option changes. ```jsx {3-6} const service = useMachine(combobox.machine, { id: useId(), onHighlightChange(details) { // details => { highlightedValue: string | null; highlightedItem: CollectionItem | null } console.log(details) }, }) ``` ### Setting the initial highlighted option Use `defaultHighlightedValue` to set which option is highlighted when the popup opens. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, defaultHighlightedValue: "ng", }) ``` ### Listening for item selection Use `onSelect` to react to each selected item. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, onSelect(details) { // details => { value: string[]; itemValue: string } console.log(details.itemValue) }, }) ``` ### Listening for value changes Use `onValueChange` to listen for selected value changes. ```jsx {3-6} const service = useMachine(combobox.machine, { onValueChange(details) { // details => { value: string[]; items: CollectionItem[] } console.log(details) }, }) ``` ### Usage within forms The combobox works in forms when you: - add a `name` so the selected value is included in `FormData`. Set `name` to enable form submission support. ```jsx {2} const service = useMachine(combobox.machine, { name: "countries", }) ``` If the input belongs to a different form element, also set `form`. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, name: "countries", form: "checkout-form", }) ``` ### Allowing custom values By default, the combobox only allows values from the collection. Set `allowCustomValue` to `true` to allow custom values. ```jsx {2} const service = useMachine(combobox.machine, { allowCustomValue: true, }) ``` ### Customizing accessibility labels Use `translations` to customize the trigger and clear button labels. ```jsx const service = useMachine(combobox.machine, { id: useId(), collection, translations: { triggerLabel: "Open countries", clearTriggerLabel: "Clear selection", }, }) ``` ## Styling guide Each combobox part includes a `data-part` attribute you can target in CSS. ### Open and closed state When the combobox opens or closes, `data-state` is added to content, control, input, and trigger parts. ```css [data-part="control"][data-state="open|closed"] { /* styles for open or closed control state */ } [data-part="input"][data-state="open|closed"] { /* styles for open or closed input state */ } [data-part="trigger"][data-state="open|closed"] { /* styles for open or closed trigger state */ } [data-part="content"][data-state="open|closed"] { /* styles for open or closed content state */ } ``` ### Focused State When the combobox is focused, the `data-focus` attribute is added to the control and label parts. ```css [data-part="control"][data-focus] { /* styles for control focus state */ } [data-part="label"][data-focus] { /* styles for label focus state */ } ``` ### Disabled State When the combobox is disabled, the `data-disabled` attribute is added to the label, control, trigger and option parts. ```css [data-part="label"][data-disabled] { /* styles for label disabled state */ } [data-part="control"][data-disabled] { /* styles for control disabled state */ } [data-part="trigger"][data-disabled] { /* styles for trigger disabled state */ } [data-part="item"][data-disabled] { /* styles for item disabled state */ } ``` ### Invalid State When the combobox is invalid, the `data-invalid` attribute is added to the root, label, control and input parts. ```css [data-part="root"][data-invalid] { /* styles for root invalid state */ } [data-part="label"][data-invalid] { /* styles for label invalid state */ } [data-part="control"][data-invalid] { /* styles for control invalid state */ } [data-part="input"][data-invalid] { /* styles for input invalid state */ } ``` ### Selected State When a combobox item is selected, the `data-state` attribute is added to the item part. ```css [data-part="item"][data-state="checked|unchecked"] { /* styles for item selected state */ } ``` ### Highlighted State When a combobox item is highlighted, the `data-highlighted` attribute is added to the item part. ```css [data-part="item"][data-highlighted] { /* styles for item highlighted state */ } ``` ## Methods and Properties ### Machine Context The combobox machine exposes the following context properties: **`open`** Type: `boolean` Description: The controlled open state of the combobox **`defaultOpen`** Type: `boolean` Description: The initial open state of the combobox when rendered. Use when you don't need to control the open state of the combobox. **`ids`** Type: `Partial<{ root: string; label: string; control: string; input: string; content: string; trigger: string; clearTrigger: string; item: (id: string, index?: number) => string; positioner: string; itemGroup: (id: string | number) => string; itemGroupLabel: (id: string | number) => string; }>` Description: The ids of the elements in the combobox. Useful for composition. **`inputValue`** Type: `string` Description: The controlled value of the combobox's input **`defaultInputValue`** Type: `string` Description: 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. **`name`** Type: `string` Description: The `name` attribute of the combobox's input. Useful for form submission **`form`** Type: `string` Description: The associate form of the combobox. **`disabled`** Type: `boolean` Description: Whether the combobox is disabled **`readOnly`** Type: `boolean` Description: Whether the combobox is readonly. This puts the combobox in a "non-editable" mode but the user can still interact with it **`invalid`** Type: `boolean` Description: Whether the combobox is invalid **`required`** Type: `boolean` Description: Whether the combobox is required **`placeholder`** Type: `string` Description: The placeholder text of the combobox's input **`defaultHighlightedValue`** Type: `string` Description: The initial highlighted value of the combobox when rendered. Use when you don't need to control the highlighted value of the combobox. **`highlightedValue`** Type: `string` Description: The controlled highlighted value of the combobox **`value`** Type: `string[]` Description: The controlled value of the combobox's selected items **`defaultValue`** Type: `string[]` Description: 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. **`inputBehavior`** Type: `"autohighlight" | "autocomplete" | "none"` Description: 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 **`selectionBehavior`** Type: `"clear" | "replace" | "preserve"` Description: 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 **`autoFocus`** Type: `boolean` Description: Whether to autofocus the input on mount **`openOnClick`** Type: `boolean` Description: Whether to open the combobox popup on initial click on the input **`openOnChange`** Type: `boolean | ((details: InputValueChangeDetails) => boolean)` Description: Whether to show the combobox when the input value changes **`allowCustomValue`** Type: `boolean` Description: Whether to allow typing custom values in the input **`alwaysSubmitOnEnter`** Type: `boolean` Description: 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. **`loopFocus`** Type: `boolean` Description: Whether to loop the keyboard navigation through the items **`positioning`** Type: `PositioningOptions` Description: The positioning options to dynamically position the menu **`onInputValueChange`** Type: `(details: InputValueChangeDetails) => void` Description: Function called when the input's value changes **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: Function called when a new item is selected **`onHighlightChange`** Type: `(details: HighlightChangeDetails) => void` Description: Function called when an item is highlighted using the pointer or keyboard navigation. **`onSelect`** Type: `(details: SelectionDetails) => void` Description: Function called when an item is selected **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: Function called when the popup is opened **`translations`** Type: `IntlTranslations` Description: Specifies the localized strings that identifies the accessibility elements and their states **`collection`** Type: `ListCollection` Description: The collection of items **`multiple`** Type: `boolean` Description: 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. **`closeOnSelect`** Type: `boolean` Description: Whether to close the combobox when an item is selected. **`openOnKeyPress`** Type: `boolean` Description: Whether to open the combobox on arrow key press **`scrollToIndexFn`** Type: `(details: ScrollToIndexDetails) => void` Description: Function to scroll to a specific index **`composite`** Type: `boolean` Description: Whether the combobox is a composed with other composite widgets like tabs **`disableLayer`** Type: `boolean` Description: Whether to disable registering this a dismissable layer **`navigate`** Type: `(details: NavigateDetails) => void` Description: Function to navigate to the selected item **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`onPointerDownOutside`** Type: `(event: PointerDownOutsideEvent) => void` Description: Function called when the pointer is pressed down outside the component **`onFocusOutside`** Type: `(event: FocusOutsideEvent) => void` Description: Function called when the focus is moved outside the component **`onInteractOutside`** Type: `(event: InteractOutsideEvent) => void` Description: Function called when an interaction happens outside the component ### Machine API The combobox `api` exposes the following methods: **`focused`** Type: `boolean` Description: Whether the combobox is focused **`open`** Type: `boolean` Description: Whether the combobox is open **`inputValue`** Type: `string` Description: The value of the combobox input **`highlightedValue`** Type: `string` Description: The value of the highlighted item **`highlightedItem`** Type: `V` Description: The highlighted item **`setHighlightValue`** Type: `(value: string) => void` Description: The value of the combobox input **`clearHighlightValue`** Type: `VoidFunction` Description: Function to clear the highlighted value **`syncSelectedItems`** Type: `VoidFunction` Description: Function to sync the selected items with the value. Useful when `value` is updated from async sources. **`selectedItems`** Type: `V[]` Description: The selected items **`hasSelectedItems`** Type: `boolean` Description: Whether there's a selected item **`value`** Type: `string[]` Description: The selected item keys **`valueAsString`** Type: `string` Description: The string representation of the selected items **`selectValue`** Type: `(value: string) => void` Description: Function to select a value **`setValue`** Type: `(value: string[]) => void` Description: Function to set the value of the combobox **`clearValue`** Type: `(value?: string) => void` Description: Function to clear the value of the combobox **`focus`** Type: `VoidFunction` Description: Function to focus on the combobox input **`setInputValue`** Type: `(value: string, reason?: InputValueChangeReason) => void` Description: Function to set the input value of the combobox **`getItemState`** Type: `(props: ItemProps) => ItemState` Description: Returns the state of a combobox item **`setOpen`** Type: `(open: boolean, reason?: OpenChangeReason) => void` Description: Function to open or close the combobox **`collection`** Type: `ListCollection` Description: Function to toggle the combobox **`reposition`** Type: `(options?: Partial) => void` Description: Function to set the positioning options **`multiple`** Type: `boolean` Description: Whether the combobox allows multiple selections **`disabled`** Type: `boolean` Description: Whether the combobox is disabled ### Data Attributes **`Root`** **`data-scope`**: combobox **`data-part`**: root **`data-invalid`**: Present when invalid **`data-readonly`**: Present when read-only **`Label`** **`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 **`Control`** **`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 **`Input`** **`data-scope`**: combobox **`data-part`**: input **`data-invalid`**: Present when invalid **`data-autofocus`**: **`data-state`**: "open" | "closed" **`Trigger`** **`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 **`Content`** **`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 **`List`** **`data-scope`**: combobox **`data-part`**: list **`data-empty`**: Present when the content is empty **`ClearTrigger`** **`data-scope`**: combobox **`data-part`**: clear-trigger **`data-invalid`**: Present when invalid **`Item`** **`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`** **`data-scope`**: combobox **`data-part`**: item-text **`data-state`**: "checked" | "unchecked" **`data-disabled`**: Present when disabled **`data-highlighted`**: Present when highlighted **`ItemIndicator`** **`data-scope`**: combobox **`data-part`**: item-indicator **`data-state`**: "checked" | "unchecked" **`ItemGroup`** **`data-scope`**: combobox **`data-part`**: item-group **`data-empty`**: Present when the content is empty ### CSS Variables ## Accessibility Adheres to the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/). ### Keyboard Interactions **`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 A date picker lets you enter a date through text input or pick one from a calendar. > **Good to know**: The date picker is built on top of the > [`@internationalized/date`](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html) > library. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/date-picker) [Logic Visualizer](https://zag-visualizer.vercel.app/date-picker) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/date-picker) **Features** - Displays a calendar view for date selection - Supports `single`, `multiple`, and `range` selection modes - Supports disabling specific dates - Supports date range presets - Supports week numbers - Supports custom format and parse logic - Works with localization, timezone, and custom calendar systems - Provides keyboard accessibility for navigating the calendar. ## Installation Install the date-picker package: ```bash npm install @zag-js/date-picker @zag-js/vue # or yarn add @zag-js/date-picker @zag-js/vue ``` ## Anatomy Check the date-picker anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the package: ```tsx import * as datepicker from "@zag-js/date-picker" ``` These are the key exports: - `machine` - Behavior logic. - `connect` - Maps behavior to JSX props and event handlers. - `parse` - Parses an ISO 8601 date string. > You'll also need to provide a unique `id` to the `useMachine` hook. This is > used to ensure that every part has a unique identifier. Then use the framework integration helpers: ```html ``` ### Setting the initial date To set the initial value rendered by the date picker, set `defaultValue`. ```tsx const service = useMachine(datepicker.machine, { defaultValue: [datepicker.parse("2022-01-01")], }) ``` ### Controlling the selected date Use the `value` and `onValueChange` properties to programmatically control the selected date. ```tsx const service = useMachine(datepicker.machine, { value: [datepicker.parse("2022-01-01")], onValueChange(details) { // details => { value: DateValue[], valueAsString: string[], view: "day" | "month" | "year" } console.log("selected date:", details.valueAsString) }, }) ``` You can also set it with `api.setValue`. ```tsx const nextValue = datepicker.parse("2022-01-01") api.setValue([nextValue]) ``` ### Controlling the open state Use `open` and `onOpenChange` to control the popup state. ```tsx const service = useMachine(datepicker.machine, { open: true, onOpenChange(details) { // details => { open: boolean, value: DateValue[] } console.log("open state changed to:", details.open) }, }) ``` You can also manage it with `api.setOpen`. ```tsx // open the date picker api.setOpen(true) // close the date picker api.setOpen(false) ``` ### Setting the min and max dates To constrain the date range that can be selected by the user, set the `min` and `max` properties. ```tsx const service = useMachine(datepicker.machine, { min: datepicker.parse("2022-01-01"), max: datepicker.parse("2022-12-31"), }) ``` When min or max is reached, previous/next triggers are disabled. ### Changing the start of the week Set `startOfWeek` from `0` to `6` (`0` is Sunday, `6` is Saturday). ```tsx const service = useMachine(datepicker.machine, { startOfWeek: 1, // Monday }) ``` ### Disabling the date picker Set `disabled` to `true` to disable the picker. ```tsx const service = useMachine(datepicker.machine, { disabled: true, }) ``` ### Rendering month and year pickers Render month and year selects with `api.getMonthSelectProps` and `api.getYearSelectProps`. ```tsx
``` ### Marking unavailable dates Set `isDateUnavailable` and return `true` for blocked dates. ```tsx import { isWeekend } from "@internationalized/date" const service = useMachine(datepicker.machine, { isDateUnavailable: (date, locale) => { // mark weekends as unavailable return isWeekend(date, locale) }, }) ``` ### Setting the calendar starting view The default view is `day`. Set `defaultView` to `day`, `month`, or `year` to change it. ```tsx const service = useMachine(datepicker.machine, { defaultView: "month", }) ``` ### Setting the read-only mode Set `readOnly` to `true` to prevent value changes. ```tsx const service = useMachine(datepicker.machine, { readOnly: true, }) ``` ### Required and invalid state Use `required` and `invalid` for form validation and UI state. ```tsx const service = useMachine(datepicker.machine, { required: true, invalid: false, }) ``` ### Setting the focused date By default, focused date is the first selected date or today. Set `defaultFocusedValue` to override it. ```tsx const service = useMachine(datepicker.machine, { defaultFocusedValue: datepicker.parse("2022-01-01"), }) ``` ### Rendering the calendar inline To render the calendar inline, set `inline` to `true`. ```tsx const service = useMachine(datepicker.machine, { inline: true, }) ``` ### Usage within a form Set `name` to include the picker in form data. ```tsx const service = useMachine(datepicker.machine, { name: "date", }) ``` ### Rendering fixed number of weeks Set `fixedWeeks` to `true` to always render 6 weeks and avoid layout jumps between months. ```tsx const service = useMachine(datepicker.machine, { fixedWeeks: true, }) ``` ### Showing week numbers Set `showWeekNumbers` to `true` to enable a week-number column in day view. ```tsx const service = useMachine(datepicker.machine, { showWeekNumbers: true, }) ``` Then render the week-number header and cells in your day table. ```tsx {api.showWeekNumbers && ( )} {api.weekDays.map((day, i) => ( ))} {api.weeks.map((week, weekIndex) => ( {api.showWeekNumbers && ( )} {week.map((value, i) => ( ))} ))}
Wk {day.narrow}
{api.getWeekNumber(week)}
{value.day}
``` ### Choosing a selection mode Use `selectionMode` to switch between `single`, `multiple`, and `range`. ```tsx const service = useMachine(datepicker.machine, { selectionMode: "multiple", }) ``` If you use `multiple`, you can cap selections with `maxSelectedDates`. ```tsx const service = useMachine(datepicker.machine, { selectionMode: "multiple", maxSelectedDates: 3, }) ``` ### Using range presets In range mode, `api.getPresetTriggerProps` accepts a preset key like `"last7Days"` or a custom `DateValue[]`. ```tsx const service = useMachine(datepicker.machine, { selectionMode: "range", }) ``` ```tsx ``` ```tsx ``` ### Customizing format and parse behavior Use `format` and `parse` to control how input text is displayed and parsed. ```tsx const service = useMachine(datepicker.machine, { format: (date, details) => date .toDate(details.timeZone) .toLocaleDateString(details.locale, { dateStyle: "short" }), parse: (value) => datepicker.parse(value), }) ``` You can also build specialized pickers: - Month-year picker: use `minView: "month"` and `placeholder: "mm/yyyy"` - Year picker: use `minView: "year"`, `defaultView: "year"`, and `placeholder: "yyyy"` ```tsx import { CalendarDate } from "@internationalized/date" const service = useMachine(datepicker.machine, { minView: "month", view: "month", placeholder: "mm/yyyy", format: (date) => `${String(date.month).padStart(2, "0")}/${date.year}`, parse: (value) => { const match = value.match(/^(\d{1,2})\/(\d{4})$/) if (!match) return undefined const [_, month, year] = match.map(Number) return new CalendarDate(year, month, 1) }, }) ``` ```tsx import { CalendarDate } from "@internationalized/date" const service = useMachine(datepicker.machine, { selectionMode: "range", minView: "year", defaultView: "year", placeholder: "yyyy", format: (date) => String(date.year), parse: (value) => { const match = value.match(/^(\d{4})$/) if (!match) return undefined const [_, year] = match.map(Number) return new CalendarDate(year, 1, 1) }, }) ``` ### Setting locale and timezone Set `locale` and `timeZone` to control date rendering. ```tsx const service = useMachine(datepicker.machine, { locale: "en-GB", timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, }) ``` ### Using custom calendar systems Pass a dedicated `createCalendar` function so you only ship the calendar your locale needs. ```tsx import { PersianCalendar } from "@internationalized/date" function createPersianCalendar(identifier: string) { if (identifier === "persian") return new PersianCalendar() throw new Error(`Unsupported calendar: ${identifier}`) } const service = useMachine(datepicker.machine, { locale: "fa-IR", createCalendar: createPersianCalendar, }) ``` ```tsx import { BuddhistCalendar } from "@internationalized/date" function createBuddhistCalendar(identifier: string) { if (identifier === "buddhist") return new BuddhistCalendar() throw new Error(`Unsupported calendar: ${identifier}`) } const service = useMachine(datepicker.machine, { locale: "th-TH", createCalendar: createBuddhistCalendar, }) ``` ### Restricting available views Use `minView` and `maxView` to limit view navigation. ```tsx const service = useMachine(datepicker.machine, { minView: "month", maxView: "year", }) ``` ### Controlling open behavior By default, the picker closes after selection and does not open on input click. You can change both behaviors. ```tsx const service = useMachine(datepicker.machine, { openOnClick: true, closeOnSelect: false, }) ``` Use `defaultOpen` if you want the calendar to start open in uncontrolled mode. ```tsx const service = useMachine(datepicker.machine, { defaultOpen: true, }) ``` ### Allowing outside-day selection Days outside the visible month are disabled by default. Set `outsideDaySelectable` to `true` if you want them selectable. ```tsx const service = useMachine(datepicker.machine, { outsideDaySelectable: true, }) ``` ### Listening to date changes Use `onValueChange` to listen for date changes. ```tsx const service = useMachine(datepicker.machine, { onValueChange(details) { // details => { value: DateValue[], valueAsString: string[], view: "day" | "month" | "year" } console.log("selected date:", details.valueAsString) }, }) ``` ### Listening to view changes Use `onViewChange` to listen for view changes. ```tsx const service = useMachine(datepicker.machine, { onViewChange(details) { // details => { view: "day" | "month" | "year" } console.log("view changed to:", details.view) }, }) ``` ### Controlling the focused date Use `focusedValue` and `onFocusChange` to control keyboard focus in the calendar. ```tsx const service = useMachine(datepicker.machine, { focusedValue: datepicker.parse("2022-01-01"), onFocusChange(details) { console.log("focused date:", details.focusedValue) }, }) ``` ### Listening to focus and visible range changes Use `onFocusChange` for focused-date changes and `onVisibleRangeChange` for visible-range changes. ```tsx const service = useMachine(datepicker.machine, { onFocusChange(details) { console.log("focused date:", details.focusedValue) }, onVisibleRangeChange(details) { console.log("visible range:", details.visibleRange) }, }) ``` ### Rendering multiple months To display multiple months: - set the `numOfMonths` prop to the desired number of months - generate the weeks for the offset months using `api.getOffset({ months: 1 })` ```tsx const service = useMachine(datepicker.machine, { // ... numOfMonths: 2, }) const offset = api.getOffset({ months: 1 }) ``` Then render the offset months. ```tsx {offset.weeks.map((week, i) => ( {week.map((value, i) => (
{value.day}
))} ))} ``` ### Positioning Use `positioning` to customize popup placement. ```tsx const service = useMachine(datepicker.machine, { positioning: { placement: "bottom-start" }, }) ``` ### Localization Use `translations` to customize accessibility labels and messages. ```tsx const service = useMachine(datepicker.machine, { translations: { clearTrigger: "Clear date", }, }) ``` ## Styling guide Each date-picker part includes a `data-part` attribute you can target in CSS. ```css [data-scope="date-picker"][data-part="root"] { /* styles for the root part */ } [data-scope="date-picker"][data-part="input"] { /* styles for the input part */ } [data-scope="date-picker"][data-part="trigger"] { /* styles for the trigger part */ } [data-scope="date-picker"][data-part="content"] { /* styles for the input part */ } ``` ### Open State ```css [data-scope="date-picker"][data-part="trigger"] { &[data-state="open"] { /* styles for the open state */ } &[data-state="closed"] { /* styles for the closed state */ } } ``` ### Cell States ```css [data-scope="date-picker"][data-part="table-cell-trigger"] { /* styles for the cell */ &[data-selected] { /* styles for the selected date */ } &[data-focus] { /* styles for the focused date */ } &[data-disabled] { /* styles for the disabled date */ } &[data-unavailable] { /* styles for the unavailable date */ } &[data-today] { /* styles for the today date */ } &[data-weekend] { /* styles for the weekend date */ } } ``` ## Methods and Properties ### Machine Context The date picker machine exposes the following context properties: **`locale`** Type: `string` Description: The locale (BCP 47 language tag) to use when formatting the date. **`createCalendar`** Type: `(identifier: CalendarIdentifier) => Calendar` Description: A function that creates a Calendar object for a given calendar identifier. Enables non-Gregorian calendar support (Persian, Buddhist, Islamic, etc.) without bundling all calendars by default. **`translations`** Type: `IntlTranslations` Description: The localized messages to use. **`ids`** Type: `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; cellTrigger: (id: string) => string; prevTrigger: (view: DateView) => string; nextTrigger: (view: DateView) => string; viewTrigger: (view: DateView) => string; clearTrigger: string; control: string; input: (index: number) => string; trigger: string; monthSelect: string; yearSelect: string; positioner: string; }>` Description: The ids of the elements in the date picker. Useful for composition. **`name`** Type: `string` Description: The `name` attribute of the input element. **`timeZone`** Type: `string` Description: The time zone to use **`disabled`** Type: `boolean` Description: Whether the calendar is disabled. **`readOnly`** Type: `boolean` Description: Whether the calendar is read-only. **`required`** Type: `boolean` Description: Whether the date picker is required **`invalid`** Type: `boolean` Description: Whether the date picker is invalid **`outsideDaySelectable`** Type: `boolean` Description: Whether day outside the visible range can be selected. **`min`** Type: `DateValue` Description: The minimum date that can be selected. **`max`** Type: `DateValue` Description: The maximum date that can be selected. **`closeOnSelect`** Type: `boolean` Description: Whether the calendar should close after the date selection is complete. This is ignored when the selection mode is `multiple`. **`openOnClick`** Type: `boolean` Description: Whether to open the calendar when the input is clicked. **`value`** Type: `DateValue[]` Description: The controlled selected date(s). **`defaultValue`** Type: `DateValue[]` Description: The initial selected date(s) when rendered. Use when you don't need to control the selected date(s) of the date picker. **`focusedValue`** Type: `DateValue` Description: The controlled focused date. **`defaultFocusedValue`** Type: `DateValue` Description: The initial focused date when rendered. Use when you don't need to control the focused date of the date picker. **`numOfMonths`** Type: `number` Description: The number of months to display. **`startOfWeek`** Type: `number` Description: The first day of the week. `0` - Sunday `1` - Monday `2` - Tuesday `3` - Wednesday `4` - Thursday `5` - Friday `6` - Saturday **`fixedWeeks`** Type: `boolean` Description: Whether the calendar should have a fixed number of weeks. This renders the calendar with 6 weeks instead of 5 or 6. **`showWeekNumbers`** Type: `boolean` Description: Whether to show the week number column in the day view. **`onValueChange`** Type: `(details: ValueChangeDetails) => void` Description: Function called when the value changes. **`onFocusChange`** Type: `(details: FocusChangeDetails) => void` Description: Function called when the focused date changes. **`onViewChange`** Type: `(details: ViewChangeDetails) => void` Description: Function called when the view changes. **`onVisibleRangeChange`** Type: `(details: VisibleRangeChangeDetails) => void` Description: Function called when the visible range changes. **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: Function called when the calendar opens or closes. **`isDateUnavailable`** Type: `(date: DateValue, locale: string) => boolean` Description: Returns whether a date of the calendar is available. **`selectionMode`** Type: `SelectionMode` Description: 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 **`maxSelectedDates`** Type: `number` Description: The maximum number of dates that can be selected. This is only applicable when `selectionMode` is `multiple`. **`format`** Type: `(date: LocaleDetails) => string` Description: The format of the date to display in the input. **`parse`** Type: `(value: string, details: LocaleDetails) => DateValue` Description: Function to parse the date from the input back to a DateValue. **`placeholder`** Type: `string` Description: The placeholder text to display in the input. **`view`** Type: `DateView` Description: The view of the calendar **`defaultView`** Type: `DateView` Description: The default view of the calendar **`minView`** Type: `DateView` Description: The minimum view of the calendar **`maxView`** Type: `DateView` Description: The maximum view of the calendar **`positioning`** Type: `PositioningOptions` Description: The user provided options used to position the date picker content **`open`** Type: `boolean` Description: The controlled open state of the date picker **`defaultOpen`** Type: `boolean` Description: 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. **`inline`** Type: `boolean` Description: Whether to render the date picker inline **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => ShadowRoot | Node | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. ### Machine API The date picker `api` exposes the following methods: **`focused`** Type: `boolean` Description: Whether the input is focused **`open`** Type: `boolean` Description: Whether the date picker is open **`disabled`** Type: `boolean` Description: Whether the date picker is disabled **`invalid`** Type: `boolean` Description: Whether the date picker is invalid **`readOnly`** Type: `boolean` Description: Whether the date picker is read-only **`inline`** Type: `boolean` Description: Whether the date picker is rendered inline **`numOfMonths`** Type: `number` Description: The number of months to display **`showWeekNumbers`** Type: `boolean` Description: Whether the week number column is shown in the day view **`selectionMode`** Type: `SelectionMode` Description: The selection mode (single, multiple, or range) **`maxSelectedDates`** Type: `number` Description: The maximum number of dates that can be selected (only for multiple selection mode). **`isMaxSelected`** Type: `boolean` Description: Whether the maximum number of selected dates has been reached. **`view`** Type: `DateView` Description: The current view of the date picker **`getWeekNumber`** Type: `(week: DateValue[]) => number` Description: Returns the ISO 8601 week number (1-53) for the given week (array of dates). **`getDaysInWeek`** Type: `(week: number, from?: DateValue) => DateValue[]` Description: Returns an array of days in the week index counted from the provided start date, or the first visible date if not given. **`getOffset`** Type: `(duration: DateDuration) => DateValueOffset` Description: Returns the offset of the month based on the provided number of months. **`getRangePresetValue`** Type: `(value: DateRangePreset) => DateValue[]` Description: Returns the range of dates based on the provided date range preset. **`getMonthWeeks`** Type: `(from?: DateValue) => DateValue[][]` Description: Returns the weeks of the month from the provided date. Represented as an array of arrays of dates. **`isUnavailable`** Type: `(date: DateValue) => boolean` Description: Returns whether the provided date is available (or can be selected) **`weeks`** Type: `DateValue[][]` Description: The weeks of the month. Represented as an array of arrays of dates. **`weekDays`** Type: `WeekDay[]` Description: The days of the week. Represented as an array of strings. **`visibleRange`** Type: `VisibleRange` Description: The visible range of dates. **`visibleRangeText`** Type: `VisibleRangeText` Description: The human readable text for the visible range of dates. **`value`** Type: `DateValue[]` Description: The selected date. **`valueAsDate`** Type: `Date[]` Description: The selected date as a Date object. **`valueAsString`** Type: `string[]` Description: The selected date as a string. **`focusedValue`** Type: `DateValue` Description: The focused date. **`focusedValueAsDate`** Type: `Date` Description: The focused date as a Date object. **`focusedValueAsString`** Type: `string` Description: The focused date as a string. **`selectToday`** Type: `VoidFunction` Description: Sets the selected date to today. **`setValue`** Type: `(values: DateValue[]) => void` Description: Sets the selected date to the given date. **`setTime`** Type: `(time: Time, index?: number) => void` Description: Sets the time for a specific date value. Converts CalendarDate to CalendarDateTime if needed. **`setFocusedValue`** Type: `(value: DateValue) => void` Description: Sets the focused date to the given date. **`clearValue`** Type: `(options?: { focus?: boolean; }) => void` Description: Clears the selected date(s). **`setOpen`** Type: `(open: boolean) => void` Description: Function to open or close the calendar. **`focusMonth`** Type: `(month: number) => void` Description: Function to set the selected month. **`focusYear`** Type: `(year: number) => void` Description: Function to set the selected year. **`getYears`** Type: `() => Cell[]` Description: Returns the months of the year **`getYearsGrid`** Type: `(props?: YearGridProps) => YearGridValue` Description: Returns the years of the decade based on the columns. Represented as an array of arrays of years. **`getDecade`** Type: `() => Range` Description: Returns the start and end years of the decade. **`getMonths`** Type: `(props?: MonthFormatOptions) => Cell[]` Description: Returns the months of the year **`getMonthsGrid`** Type: `(props?: MonthGridProps) => MonthGridValue` Description: Returns the months of the year based on the columns. Represented as an array of arrays of months. **`format`** Type: `(value: DateValue, opts?: Intl.DateTimeFormatOptions) => string` Description: Formats the given date value based on the provided options. **`setView`** Type: `(view: DateView) => void` Description: Sets the view of the date picker. **`goToNext`** Type: `VoidFunction` Description: Goes to the next month/year/decade. **`goToPrev`** Type: `VoidFunction` Description: Goes to the previous month/year/decade. **`getDayTableCellState`** Type: `(props: DayTableCellProps) => DayTableCellState` Description: Returns the state details for a given cell. **`getMonthTableCellState`** Type: `(props: TableCellProps) => TableCellState` Description: Returns the state details for a given month cell. **`getYearTableCellState`** Type: `(props: TableCellProps) => TableCellState` Description: Returns the state details for a given year cell. ### Data Attributes **`Root`** **`data-scope`**: date-picker **`data-part`**: root **`data-state`**: "open" | "closed" **`data-disabled`**: Present when disabled **`data-readonly`**: Present when read-only **`data-empty`**: Present when the content is empty **`Label`** **`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 **`Control`** **`data-scope`**: date-picker **`data-part`**: control **`data-disabled`**: Present when disabled **`data-placeholder-shown`**: Present when placeholder is shown **`Content`** **`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 **`Table`** **`data-scope`**: date-picker **`data-part`**: table **`data-columns`**: **`data-view`**: The view of the table **`TableHead`** **`data-scope`**: date-picker **`data-part`**: table-head **`data-view`**: The view of the tablehead **`data-disabled`**: Present when disabled **`TableHeader`** **`data-scope`**: date-picker **`data-part`**: table-header **`data-view`**: The view of the tableheader **`data-disabled`**: Present when disabled **`TableBody`** **`data-scope`**: date-picker **`data-part`**: table-body **`data-view`**: The view of the tablebody **`data-disabled`**: Present when disabled **`TableRow`** **`data-scope`**: date-picker **`data-part`**: table-row **`data-disabled`**: Present when disabled **`data-view`**: The view of the tablerow **`WeekNumberHeaderCell`** **`data-scope`**: date-picker **`data-part`**: week-number-header-cell **`data-view`**: The view of the weeknumberheadercell **`data-type`**: The type of the item **`data-disabled`**: Present when disabled **`WeekNumberCell`** **`data-scope`**: date-picker **`data-part`**: week-number-cell **`data-view`**: The view of the weeknumbercell **`data-week-index`**: **`data-type`**: The type of the item **`data-disabled`**: Present when disabled **`DayTableCell`** **`data-scope`**: date-picker **`data-part`**: day-table-cell **`data-value`**: The value of the item **`DayTableCellTrigger`** **`data-scope`**: date-picker **`data-part`**: day-table-cell-trigger **`data-disabled`**: Present when disabled **`data-selected`**: Present when selected **`data-value`**: The value of the item **`data-view`**: The view of the daytablecelltrigger **`data-today`**: Present when the date represents today **`data-focus`**: Present when focused **`data-unavailable`**: Present when the date is unavailable based on the min and max date **`data-range-start`**: Present when is the start of a range **`data-range-end`**: Present when is the end of a range **`data-in-range`**: Present when is within the range **`data-outside-range`**: Present when is outside the range **`data-weekend`**: Present when is a weekend day **`data-in-hover-range`**: Present when in hovered range **`data-hover-range-start`**: Present when is the start of the hovered range **`data-hover-range-end`**: Present when is the end of the hovered range **`MonthTableCell`** **`data-scope`**: date-picker **`data-part`**: month-table-cell **`data-selected`**: Present when selected **`data-value`**: The value of the item **`MonthTableCellTrigger`** **`data-scope`**: date-picker **`data-part`**: month-table-cell-trigger **`data-selected`**: Present when selected **`data-disabled`**: Present when disabled **`data-focus`**: Present when focused **`data-in-range`**: Present when is within the range **`data-outside-range`**: Present when is outside the range **`data-view`**: The view of the monthtablecelltrigger **`data-value`**: The value of the item **`YearTableCell`** **`data-scope`**: date-picker **`data-part`**: year-table-cell **`data-selected`**: Present when selected **`data-value`**: The value of the item **`YearTableCellTrigger`** **`data-scope`**: date-picker **`data-part`**: year-table-cell-trigger **`data-selected`**: Present when selected **`data-focus`**: Present when focused **`data-in-range`**: Present when is within the range **`data-disabled`**: Present when disabled **`data-outside-range`**: Present when is outside the range **`data-value`**: The value of the item **`data-view`**: The view of the yeartablecelltrigger **`NextTrigger`** **`data-scope`**: date-picker **`data-part`**: next-trigger **`data-disabled`**: Present when disabled **`PrevTrigger`** **`data-scope`**: date-picker **`data-part`**: prev-trigger **`data-disabled`**: Present when disabled **`Trigger`** **`data-scope`**: date-picker **`data-part`**: trigger **`data-placement`**: The placement of the trigger **`data-state`**: "open" | "closed" **`data-placeholder-shown`**: Present when placeholder is shown **`View`** **`data-scope`**: date-picker **`data-part`**: view **`data-view`**: The view of the view **`ViewTrigger`** **`data-scope`**: date-picker **`data-part`**: view-trigger **`data-view`**: The view of the viewtrigger **`ViewControl`** **`data-scope`**: date-picker **`data-part`**: view-control **`data-view`**: The view of the viewcontrol **`Input`** **`data-scope`**: date-picker **`data-part`**: input **`data-index`**: The index of the item **`data-state`**: "open" | "closed" **`data-placeholder-shown`**: Present when placeholder is shown **`data-invalid`**: Present when invalid ### CSS Variables A dialog is a window overlaid on either the primary window or another dialog window. Content behind a modal dialog is inert, meaning that users cannot interact with it. ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/dialog) [Logic Visualizer](https://zag-visualizer.vercel.app/dialog) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/dialog) **Features** - Supports modal and non-modal modes - Focus is trapped and scrolling is blocked in the modal mode - Provides screen reader announcements via rendered title and description - Pressing `Esc` closes the dialog ## Installation Install the dialog package: ```bash npm install @zag-js/dialog @zag-js/vue # or yarn add @zag-js/dialog @zag-js/vue ``` ## Anatomy To use the dialog component correctly, you'll need to understand its anatomy and how we name its parts. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the dialog package: ```jsx import * as dialog from "@zag-js/dialog" ``` The dialog package exports two key functions: - `machine` - Behavior logic for the dialog. - `connect` - Maps behavior to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Managing focus within the dialog When the dialog opens, it focuses the first focusable element and keeps keyboard focus inside the dialog. To control what receives focus on open, pass `initialFocusEl`. ```html {5,8,13} ``` To control what receives focus when the dialog closes, pass `finalFocusEl`. ### Dialog vs non-modal dialog Set `modal` to `false` to allow interaction with content behind the dialog. ```jsx const service = useMachine(dialog.machine, { modal: false, }) ``` ### Closing the dialog on interaction outside By default, the dialog closes when you click its overlay. You can set `closeOnInteractOutside` to `false` if you want the modal to stay visible. ```jsx {2} const service = useMachine(dialog.machine, { closeOnInteractOutside: false, }) ``` You can also customize the behavior by passing a function to the `onInteractOutside` callback and calling `event.preventDefault()`. ```jsx {2-7} const service = useMachine(dialog.machine, { onInteractOutside(event) { const target = event.target if (target?.closest("")) { return event.preventDefault() } }, }) ``` ### Listening for open state changes When the dialog is opened or closed, the `onOpenChange` callback is invoked. ```jsx {2-7} const service = useMachine(dialog.machine, { onOpenChange(details) { // details => { open: boolean } console.log("open:", details.open) }, }) ``` ### Closing with Escape Set `closeOnEscape` to `false` if the dialog should not close on `Esc`. ```jsx const service = useMachine(dialog.machine, { closeOnEscape: false, }) ``` ### Controlled dialog To control the dialog's open state, pass the `open` and `onOpenChange` properties. ```html ``` ### Controlling the scroll behavior When the dialog is open, it prevents scrolling on the `body` element. To disable this behavior, set `preventScroll` to `false`. ```jsx {2} const service = useMachine(dialog.machine, { preventScroll: false, }) ``` ### Creating an alert dialog The dialog supports both `dialog` and `alertdialog` roles. It uses `dialog` by default. Set `role` to `alertdialog` for urgent actions. That's it! Now you have an alert dialog. ```jsx {2} const service = useMachine(dialog.machine, { role: "alertdialog", }) ``` > By definition, an alert dialog will contain two or more action buttons. We > recommend setting focus to the least destructive action via `initialFocusEl`. ### Labeling without a visible title If you do not render a title element, provide `aria-label`. ```jsx const service = useMachine(dialog.machine, { "aria-label": "Delete project", }) ``` ## Styling guide Each part includes a `data-part` attribute you can target in CSS. ```css [data-part="trigger"] { /* styles for the trigger element */ } [data-part="backdrop"] { /* styles for the backdrop element */ } [data-part="positioner"] { /* styles for the positioner element */ } [data-part="content"] { /* styles for the content element */ } [data-part="title"] { /* styles for the title element */ } [data-part="description"] { /* styles for the description element */ } [data-part="close-trigger"] { /* styles for the close trigger element */ } ``` ### Open and closed state The dialog has two states: `open` and `closed`. You can use the `data-state` attribute to style the dialog or trigger based on its state. ```css [data-part="content"][data-state="open|closed"] { /* styles for the open state */ } [data-part="trigger"][data-state="open|closed"] { /* styles for the open state */ } ``` ### Nested dialogs When dialogs are nested (a dialog opened from within another dialog), the layer stack automatically applies data attributes to help create visual hierarchy. - `data-nested` - Applied to nested dialogs - `data-has-nested` - Applied to dialogs that have nested dialogs open - `--nested-layer-count` - CSS variable indicating the number of nested dialogs ```css /* Scale down parent dialogs when they have nested children */ [data-part="content"][data-has-nested] { transform: scale(calc(1 - var(--nested-layer-count) * 0.05)); transition: transform 0.2s ease-in-out; } /* Style nested dialogs differently */ [data-part="content"][data-nested] { border: 2px solid var(--accent-color); } /* Create depth effect using backdrop opacity */ [data-part="backdrop"][data-has-nested] { opacity: calc(0.4 + var(--nested-layer-count) * 0.1); } ``` ## Methods and Properties ### Machine Context The dialog machine exposes the following context properties: **`ids`** Type: `Partial<{ trigger: string; positioner: string; backdrop: string; content: string; closeTrigger: string; title: string; description: string; }>` Description: The ids of the elements in the dialog. Useful for composition. **`trapFocus`** Type: `boolean` Description: Whether to trap focus inside the dialog when it's opened **`preventScroll`** Type: `boolean` Description: Whether to prevent scrolling behind the dialog when it's opened **`modal`** Type: `boolean` Description: Whether to prevent pointer interaction outside the element and hide all content below it **`initialFocusEl`** Type: `() => HTMLElement` Description: Element to receive focus when the dialog is opened **`finalFocusEl`** Type: `() => HTMLElement` Description: Element to receive focus when the dialog is closed **`restoreFocus`** Type: `boolean` Description: Whether to restore focus to the element that had focus before the dialog was opened **`closeOnInteractOutside`** Type: `boolean` Description: Whether to close the dialog when the outside is clicked **`closeOnEscape`** Type: `boolean` Description: Whether to close the dialog when the escape key is pressed **`aria-label`** Type: `string` Description: Human readable label for the dialog, in event the dialog title is not rendered **`role`** Type: `"dialog" | "alertdialog"` Description: The dialog's role **`open`** Type: `boolean` Description: The controlled open state of the dialog **`defaultOpen`** Type: `boolean` Description: The initial open state of the dialog when rendered. Use when you don't need to control the open state of the dialog. **`onOpenChange`** Type: `(details: OpenChangeDetails) => void` Description: Function to call when the dialog's open state changes **`dir`** Type: `"ltr" | "rtl"` Description: The document's text/writing direction. **`id`** Type: `string` Description: The unique identifier of the machine. **`getRootNode`** Type: `() => Node | ShadowRoot | Document` Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. **`onEscapeKeyDown`** Type: `(event: KeyboardEvent) => void` Description: Function called when the escape key is pressed **`onRequestDismiss`** Type: `(event: LayerDismissEvent) => void` Description: Function called when this layer is closed due to a parent layer being closed **`onPointerDownOutside`** Type: `(event: PointerDownOutsideEvent) => void` Description: Function called when the pointer is pressed down outside the component **`onFocusOutside`** Type: `(event: FocusOutsideEvent) => void` Description: Function called when the focus is moved outside the component **`onInteractOutside`** Type: `(event: InteractOutsideEvent) => void` Description: Function called when an interaction happens outside the component **`persistentElements`** Type: `(() => Element)[]` Description: Returns the persistent elements that: - should not have pointer-events disabled - should not trigger the dismiss event ### Machine API The dialog `api` exposes the following methods: **`open`** Type: `boolean` Description: Whether the dialog is open **`setOpen`** Type: `(open: boolean) => void` Description: Function to open or close the dialog ### Data Attributes **`Trigger`** **`data-scope`**: dialog **`data-part`**: trigger **`data-state`**: "open" | "closed" **`Backdrop`** **`data-scope`**: dialog **`data-part`**: backdrop **`data-state`**: "open" | "closed" **`Content`** **`data-scope`**: dialog **`data-part`**: content **`data-state`**: "open" | "closed" **`data-nested`**: dialog **`data-has-nested`**: dialog ### CSS Variables ## Accessibility Adheres to the [Alert and Message Dialogs WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog). ### Keyboard Interactions **`Enter`** Description: When focus is on the trigger, opens the dialog. **`Tab`** Description: Moves focus to the next focusable element within the content. Focus is trapped within the dialog. **`Shift + Tab`** Description: Moves focus to the previous focusable element. Focus is trapped within the dialog. **`Esc`** Description: Closes the dialog and moves focus to trigger or the defined final focus element Editable is an input field used for editing a single line of text. It renders as static text and transforms into a text input field when the edit interaction is triggered (click, focus, or double-click). ## Resources [Latest version: v1.35.2](https://www.npmjs.com/package/@zag-js/editable) [Logic Visualizer](https://zag-visualizer.vercel.app/editable) [Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/editable) **Features** - Use custom controls for the editable - Pressing `Enter` commits the input value - Pressing `Esc` reverts the value - Activate edit mode by double-clicking or focusing on the preview text - Auto-resize input to fit content ## Installation Install the editable package: ```bash npm install @zag-js/editable @zag-js/vue # or yarn add @zag-js/editable @zag-js/vue ``` ## Anatomy Check the editable anatomy and part names. > Each part includes a `data-part` attribute to help identify them in the DOM. ## Usage Import the editable package: ```jsx import * as editable from "@zag-js/editable" ``` The editable package exports two key functions: - `machine` - Behavior logic for the editable. - `connect` - Maps behavior to JSX props and event handlers. > Pass a unique `id` to `useMachine` so generated element ids stay predictable. Then use the framework integration helpers: ```html ``` ### Setting the initial value Set `defaultValue` to define the initial value. ```jsx {2} const service = useMachine(editable.machine, { defaultValue: "Hello World", }) ``` ### Controlled value Use `value` and `onValueChange` to control the value externally. ```jsx const service = useMachine(editable.machine, { value, onValueChange(details) { setValue(details.value) }, }) ``` ### Controlled edit state Use `edit` and `onEditChange` to control whether the field is in edit mode. ```jsx const service = useMachine(editable.machine, { edit, onEditChange(details) { setEdit(details.edit) }, }) ``` ### Listening for value changes Editable supports two ways of listening for value changes: - `onValueChange`: called when value changes. - `onValueCommit`: called when the value is committed. ```jsx {2-4} const service = useMachine(editable.machine, { onValueChange(details) { console.log("Value changed", details.value) }, onValueCommit(details) { console.log("Value submitted", details.value) }, }) ``` ### Listening for revert events Use `onValueRevert` to react when a user cancels editing. ```jsx const service = useMachine(editable.machine, { onValueRevert(details) { console.log("Value reverted", details.value) }, }) ``` ### Using custom controls In some cases, you might need to use custom controls to toggle the edit and read mode. We use the render prop pattern to provide access to the internal state of the component. ```html ``` ### Auto-resizing Set `autoResize` to `true` to auto-grow the editable as content changes. ```jsx {2} const service = useMachine(editable.machine, { autoResize: true, }) ``` When using autoresize, the input and preview elements should not have any styles. Use `all: unset` if needed and pass any styles to the "area" element since it's shared by the input and preview elements. ### Setting a maxWidth It is common to set a max width when auto-resizing. ```jsx {2-3} const service = useMachine(editable.machine, { autoResize: true, maxWidth: "320px", }) ``` When the editable reaches the specified max-width, it'll clip the preview text with an ellipsis. ### Editing with double click The editable supports two modes of activating the "edit" state: - when the preview part is focused (with pointer or keyboard). - when the preview part is double-clicked. Set `activationMode` to `"dblclick"` to only enter edit mode on double click. ```jsx {2} const service = useMachine(editable.machine, { activationMode: "dblclick", }) ``` ### Customizing submit behavior Use `submitMode` to control when edits are committed. ```jsx const service = useMachine(editable.machine, { submitMode: "enter", // "enter" | "blur" | "both" | "none" }) ``` ### Usage with Textarea Editable supports using a `textarea` instead of an `input` field. When a textarea is used, the editable will commit the value on `Cmd + Enter` or `Ctrl + Enter`. > Use `api.getInputProps()` to spread input props to the textarea. You might > need to cast the input props to the correct type. ```tsx {2}