# Accordion

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.5.0](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.
- Can expand one or multiple items.
- Collapse each accordion item.

## Installation

To use the accordion machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/accordion @zag-js/react
# or
yarn add @zag-js/accordion @zag-js/react
```


This command will install the framework agnostic accordion logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the accordion 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

First, import the accordion package into your project

```jsx
import * as accordion from "@zag-js/accordion"
```

The accordion package exports two key functions:

- `machine` — The state machine logic for the accordion widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
accordion machine in your project 🔥

```jsx
import * as accordion from "@zag-js/accordion"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

const data = [
  { title: "Watercraft", content: "Sample accordion content" },
  { title: "Automobiles", content: "Sample accordion content" },
  { title: "Aircraft", content: "Sample accordion content" },
]

function Accordion() {
  const service = useMachine(accordion.machine, { id: useId() })

  const api = accordion.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {data.map((item) => (
        <div key={item.title} {...api.getItemProps({ value: item.title })}>
          <h3>
            <button {...api.getItemTriggerProps({ value: item.title })}>
              {item.title}
            </button>
          </h3>
          <div {...api.getItemContentProps({ value: item.title })}>
            {item.content}
          </div>
        </div>
      ))}
    </div>
  )
}
```


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 accordions at once

To allow multiple items to be expanded at once, set `multiple` to `true`. This
mode implicitly sets `collapsible` to `true` and ensures that each accordion can
be expanded.

```jsx {2}
const service = useMachine(accordion.machine, {
  multiple: true,
})
```

## Opening specific accordions

To set the value of the accordion(s) that should be opened initially, pass the
`value` property to the machine function.

```jsx {3,4,9}
// for multiple accordions
const service = useMachine(accordion.machine, {
  multiple: true,
  defaultValue: ["home"],
})

// for single accordions
const service = useMachine(accordion.machine, {
  defaultValue: ["home"],
})
```

## Toggle each accordion item

To collapse an already expanded accordion item by clicking on it, set the
context's `collapsible` property to `true`.

> Note: If `multiple` is `true`, we internally set `collapsible` to be `true`.

```jsx {2}
const service = useMachine(accordion.machine, {
  collapsible: true,
})
```

## Listening for 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)
  },
})
```

## 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
//...
<div {...api.getItemProps({ value: "item", disabled: true })}>
  <h3>
    <button {...api.getItemTriggerProps({ value: "item", disabled: true })}>
      Trigger
    </button>
  </h3>
  <div {...api.getItemContentProps({ value: "item", disabled: true })}>
    Content
  </div>
</div>
//...
```

You can also disable the entire accordion items by passing `disabled` to the
machine's context.

```jsx {2}
const service = useMachine(accordion.machine, {
  disabled: true,
})
```

## Styling guide

Earlier, we mentioned that each accordion part has a `data-part` attribute added
to them to select and style them in the DOM.

### Open and closed state

When an accordion item is expanded or collapsed, a `data-state` attribute is set
on the item, trigger and content elements. This attribute is removed when it is
closed.

```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 Component

Create your accordion component by abstracting the machine into your own
component.

### Usage

```tsx
import { Accordion } from "./your-accordion"

function Demo() {
  return (
    <Accordion
      defaultValue={["1"]}
      items={[
        { value: "1", title: "Title 1", content: "Content 1" },
        { value: "2", title: "Title 2", content: "Content 2" },
      ]}
    />
  )
}
```


### Implementation

Use the the `splitProps` utility to separate the machine's props from the
component's props.

```tsx
import * as accordion from "@zag-js/accordion"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

interface Item {
  value: string
  title: React.ReactNode
  content: React.ReactNode
}

export interface AccordionProps extends Omit<accordion.Props, "id"> {
  items: Item[]
}

export function Accordion(props: AccordionProps) {
  const [machineProps, localProps] = accordion.splitProps(props)

  const service = useMachine(accordion.machine, {
    id: useId(),
    ...machineProps,
  })

  const api = accordion.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {localProps.items.map((item) => (
        <div {...api.getItemProps({ value: item.value })}>
          <h3>
            <button {...api.getItemTriggerProps({ value: item.value })}>
              {item.title}
            </button>
          </h3>
          <div {...api.getItemContentProps({ value: item.value })}>
            {item.content}
          </div>
        </div>
      ))}
    </div>
  )
}
```


## 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: Gets 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-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.



# Angle Slider

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.5.0](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 track to update value.
- Supports Right-to-Left directionality.

## Installation

To use the angle slider machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/angle-slider @zag-js/react
# or
yarn add @zag-js/angle-slider @zag-js/react
```


This command will install the framework agnostic angle slider logic and the
reactive utilities for your framework of choice.

## 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

First, import the angle-slider package into your project

```jsx
import * as angleSlider from "@zag-js/angle-slider"
```

The angle slider package exports two key functions:

- `machine` — The state machine logic for the angle slider widget as described
  in the WAI-ARIA spec.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
angle slider machine in your project 🔥

```jsx
import * as angleSlider from "@zag-js/angle-slider"
import { normalizeProps, useMachine } from "@zag-js/react"

export function AngleSlider() {
  const service = useMachine(angleSlider.machine, { id: "1" })

  const api = angleSlider.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Wind direction</label>
      <div {...api.getControlProps()}>
        <div {...api.getThumbProps()}></div>
        <div {...api.getMarkerGroupProps()}>
          {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => (
            <div key={value} {...api.getMarkerProps({ value })}></div>
          ))}
        </div>
      </div>
      <div {...api.getValueTextProps()}>{api.value} degrees</div>
      <input {...api.getHiddenInputProps()} />
    </div>
  )
}
```


## Setting the initial value

```jsx {2}
const service = useMachine(angleSlider.machine, {
  defaultValue: 45,
})
```

## Setting the value's granularity

By default, the granularity, is `1`, meaning that the value is always an
integer. You can change the step attribute to control the granularity.

For example, If you need a value between `5` and `10`, accurate to two decimal
places, you should set the value of step to `0.01`:

```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. You can use this to setup custom behaviors in your app.

```jsx {2-7}
const service = useMachine(angleSlider.machine, {
  onValueChange(details) {
    console.log("value is changing to:", details)
  },
  onValueChangeEnd(details) {
    console.log("value has changed to:", details)
  },
})
```

## Usage within forms

To use angle slider within forms, use the exposed `hiddenInputProps` from the
`connect` function and ensure you pass `name` value to the machine's context. It
will render a hidden input and ensure the value changes get propagated to the
form correctly.

```jsx {2}
const service = useMachine(angleSlider.machine, {
  name: "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.

```jsx {7-11}
//...

<div {...api.getRootProps()}>
  <label {...api.getLabelProps()}>Wind direction</label>
  <div {...api.getControlProps()}>
    <div {...api.getThumbProps()}></div>
    <div {...api.getMarkerGroupProps()}>
      {[0, 45, 90, 135, 180, 225, 270, 315].map((value) => (
        <div key={value} {...api.getMarkerProps({ value })}></div>
      ))}
    </div>
  </div>
  <div {...api.getValueTextProps()}>{api.value} degrees</div>
  <input {...api.getHiddenInputProps()} />
</div>
//...
```


## Styling guide

Earlier, we mentioned that each angle slider part has a `data-part` attribute
added to them to select and style them in the DOM.

### 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 slider machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; thumb: string; hiddenInput: string; control: string; valueText: 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.

**`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 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

### Keyboard Interactions

**`ArrowRight`**
Description: <span>Increments the angle slider based on defined step</span>

**`ArrowLeft`**
Description: <span>Decrements the angle slider based on defined step</span>

**`ArrowUp`**
Description: <span>Decreases the value by the step amount.</span>

**`ArrowDown`**
Description: <span>Increases the value by the step amount.</span>

**`Shift + ArrowUp`**
Description: <span>Decreases the value by a larger step</span>

**`Shift + ArrowDown`**
Description: <span>Increases the value by a larger step</span>

**`Home`**
Description: Sets the value to 0 degrees.

**`End`**
Description: Sets the value to 360 degrees.



# Avatar

The Avatar component is a React component that represents a user avatar or
profile picture. It displays an image or initials within container.

Avatar provides support for fallback text or elements when the image fails to
load, or when the image is not provided.

## Resources


[Latest version: v1.5.0](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

To use the avatar machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/avatar @zag-js/react
# or
yarn add @zag-js/avatar @zag-js/react
```


This command will install the framework agnostic avatar logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the avatar 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

First, import the avatar package into your project

```jsx
import * as avatar from "@zag-js/avatar"
```

The avatar package exports two key functions:

- `machine` — The state machine logic for the avatar widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
avatar machine in your project 🔥

```jsx
import * as avatar from "@zag-js/avatar"
import { useMachine, normalizeProps } from "@zag-js/react"

function Avatar() {
  const service = useMachine(avatar.machine, { id: "1" })

  const api = avatar.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <span {...api.getFallbackProps()}>PA</span>
      <img alt="PA" src={src} {...api.getImageProps()} />
    </div>
  )
}
```


## Listening for loading status changes

When the image has loaded or failed to load, the `onStatusChange` callback is
invoked.

```jsx {2}
const service = useMachine(avatar.machine, {
  onStatusChange(details) {
    // details => { status: "error" | "loaded" }
  },
})
```

## Styling guide

Earlier, we mentioned that each avatar part has a `data-part` attribute added to
them to select and style them in the DOM.

```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 Component

Create your avatar component by abstracting the machine into your own component.

### Usage

```tsx
import { Avatar } from "./your-avatar"

function Demo() {
  return (
    <Avatar
      src="https://avatars.githubusercontent.com/u/139426"
      name="John Doe"
    />
  )
}
```


### Implementation

Use the the `splitProps` utility to separate the machine's props from the
component's props.

```tsx
import * as avatar from "@zag-js/avatar"
import { useMachine, normalizeProps } from "@zag-js/react"

export interface AvatarProps extends Omit<avatar.Context, "id"> {
  /**
   * The src of the avatar image
   */
  src?: string
  /**
   * The srcSet of the avatar image
   */
  srcSet?: string
  /**
   * The name of the avatar
   */
  name: string
}

function Avatar(props: AvatarProps) {
  const [machineProps, localProps] = avatar.splitProps(props)

  const service = useMachine(avatar.machine, {
    id: useId(),
    ...machineProps,
  })

  const api = avatar.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <span {...api.getFallbackProps()}>{getInitials(localProps.name)}</span>
      <img
        alt="PA"
        src={localProps.src}
        srcSet={localProps.srcSet}
        {...api.getImageProps()}
      />
    </div>
  )
}

function getInitials(name: string) {
  return name
    .split(" ")
    .map((word) => word[0])
    .join("")
}
```


## 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: `() => void`
Description: Function to set loaded state.

**`setError`**
Type: `() => void`
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"



# Carousel

an accessible carousel component that leverages native CSS Scroll Snap for
smooth, performant scrolling between slides.

## Resources


[Latest version: v1.5.0](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 alignment of slides (start, center or end alignment).
- Show multiple slides at a time.
- Supports looping and auto-playing.
- Supports custom spacing between slides.

## Installation

To use the carousel machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/carousel @zag-js/react
# or
yarn add @zag-js/carousel @zag-js/react
```


This command will install the framework agnostic carousel logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the carousel 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

First, import the carousel package into your project

```jsx
import * as carousel from "@zag-js/carousel"
```

The carousel package exports two key functions:

- `machine` — The state machine logic for the carousel widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
carousel machine in your project 🔥

> **Note:** The carousel requires that you provide a `slideCount` property in
> the machine's context. This is the number of slides in the carousel.

```jsx
import * as carousel from "@zag-js/carousel"
import { normalizeProps, useMachine } from "@zag-js/react"

const items = [
  "https://tinyurl.com/5b6ka8jd",
  "https://tinyurl.com/7rmccdn5",
  "https://tinyurl.com/59jxz9uu",
]

export function Carousel() {
  const service = useMachine(carousel.machine, {
    id: "1",
    slideCount: items.length,
  })

  const api = carousel.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getControlProps()}>
        <button {...api.getPrevTriggerProps()}>Prev</button>
        <button {...api.getNextTriggerProps()}>Next</button>
      </div>
      <div {...api.getItemGroupProps()}>
        {items.map((image, index) => (
          <div {...api.getItemProps({ index })} key={index}>
            <img
              src={image}
              alt=""
              style={{ height: "300px", width: "100%", objectFit: "cover" }}
            />
          </div>
        ))}
      </div>
      <div {...api.getIndicatorGroupProps()}>
        {api.pageSnapPoints.map((_, index) => (
          <button {...api.getIndicatorProps({ index })} key={index} />
        ))}
      </div>
    </div>
  )
}
```


## Vertical carousel

To create a vertical carousel, set the `orientation` property in the machine's
context to `vertical`.

```jsx {2}
const service = useMachine(carousel.machine, {
  orientation: "vertical",
})
```

## Setting the initial slide

To set the initial slide of the carousel, pass the `page` property to the
machine's context.

The `page` 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,
})
```

## Setting the number of slides to show at a time

To customize number of slides to show at a time, set the `slidesPerPage`
property in the machine's context. The value must be an integer.

```jsx {2}
const service = useMachine(carousel.machine, {
  slidesPerPage: 2,
})
```

## Setting the number of slides to move at a time

To customize number of slides to move at a time, set the `slidesPerMove`
property in the machine's context. The value must be an integer or `auto`.

> If the value is `auto`, the carousel will move the number of slides equal to
> the number of slides per page.

```jsx {2}
const service = useMachine(carousel.machine, {
  slidesPerMove: 2,
})
```

> Ensure the `slidesPerMove` is less than or equal to the `slidesPerPage` to
> avoid skipping slides.

## Setting the carousel should loop around

To allow looping of slides, set the `loop` property in the machine's context to
`true`.

```jsx {2}
const service = useMachine(carousel.machine, {
  loop: true,
})
```

## Setting the gap between slides

To customize spacing between slides, set the `spacing` property in the machine's
context to a valid CSS unit.

```jsx {2}
const service = useMachine(carousel.machine, {
  spacing: "16px",
})
```

## 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)
  },
})
```

## Dragging the carousel

To allow dragging the carousel with the mouse, set the `allowMouseDrag` property
in the machine's context to `true`.

```jsx {2}
const service = useMachine(carousel.machine, {
  allowMouseDrag: true,
})
```

## Autoplaying the carousel

To allow the carousel to autoplay, set the `autoplay` property in the machine's
context to `true`.

```jsx {2}
const service = useMachine(carousel.machine, {
  autoplay: true,
})
```

Alternatively, you can configure the autoplay interval by setting the `delay`
property in the machine's context.

```jsx {2}
const service = useMachine(carousel.machine, {
  autoplay: { delay: 2000 },
})
```

## Styling guide

Earlier, we mentioned that each carousel part has a `data-part` attribute added
to them to select and style them in the DOM.

```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.

**`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

**`play`**
Type: `() => void`
Description: Function to start/resume autoplay

**`pause`**
Type: `() => void`
Description: Function to pause autoplay

**`isInView`**
Type: `(index: number) => boolean`
Description: Whether the item is in view

**`refresh`**
Type: `() => void`
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



# Checkbox

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.5.0](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. i.e. `indeterminate` state
- Syncs with `disabled` state of fieldset
- Syncs with form `reset` events
- Can be toggled programmatically

## Installation

To use the checkbox machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/checkbox @zag-js/react
# or
yarn add @zag-js/checkbox @zag-js/react
```


This command will install the framework agnostic checkbox logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the checkbox 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

First, import the checkbox package into your project

```jsx
import * as checkbox from "@zag-js/checkbox"
```

The checkbox package exports two key functions:

- `machine` — The state machine logic for the checkbox widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
checkbox machine in your project 🔥

```jsx
import * as checkbox from "@zag-js/checkbox"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

function Checkbox() {
  const service = useMachine(checkbox.machine, { id: useId() })

  const api = checkbox.connect(service, normalizeProps)

  return (
    <label {...api.getRootProps()}>
      <span {...api.getLabelProps()}>
        Input is {api.checked ? "checked" : "unchecked"}
      </span>
      <div {...api.getControlProps()} />
      <input {...api.getHiddenInputProps()} />
    </label>
  )
}
```


## Indeterminate checkboxes

To make a checkbox indeterminate, set the context's `indeterminate` property to
true

```jsx {2}
const service = useMachine(checkbox.machine, {
  indeterminate: true,
})
```

## Disabling the checkbox

To make a checkbox disabled, set the context's `disabled` property to true

```jsx {2}
const service = useMachine(checkbox.machine, {
  disabled: true,
})
```

## Making it checked by default

To make a checkbox checked by default, set the context's `checked` property to
`true`

```jsx {2}
const service = useMachine(checkbox.machine, {
  defaultChecked: true,
})
```

## Listening for changes

When the checkbox value changes, the `onCheckChange` callback is invoked.

```jsx {2-5}
const service = useMachine(checkbox.machine, {
  onCheckChange(details) {
    // details => { checked: boolean }
    console.log("checkbox is:", details.checked)
  },
})
```

## Usage within forms

To use checkbox within forms, use the exposed `hiddenInputProps` from the
`connect` function and ensure you pass `name` value to the machine's context. It
will render a hidden input and ensure the value changes get propagated to the
form correctly.

```jsx {2}
const service = useMachine(checkbox.machine, {
  name: "fruits",
})
```

## Styling guide

Earlier, we mentioned that each checkbox part has a `data-part` attribute added
to them to select and style them in the DOM.

### Checked state

When the checkbox input is checked, the `data-checked` 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: `() => void`
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

**`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

**`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

**`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

## Accessibility

### Keyboard Interactions

**`Space`**
Description: Toggle the checkbox



# Clipboard

The clipboard machine allows users to quickly copy content to clipboard.

## Resources


[Latest version: v1.5.0](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

To use the clipboard machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/clipboard @zag-js/react
# or
yarn add @zag-js/clipboard @zag-js/react
```


This command will install the framework agnostic clipboard logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the clipboard 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

First, import the clipboard package into your project

```jsx
import * as clipboard from "@zag-js/clipboard"
```

The clipboard package exports two key functions:

- `machine` — The state machine logic for the clipboard widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
clipboard machine in your project 🔥

```tsx
import * as clipboard from "@zag-js/clipboard"
import { useMachine, normalizeProps } from "@zag-js/react"
import { ClipboardCheck, ClipboardCopyIcon } from "lucide-react"
import { useId } from "react"

function Clipboard() {
  const service = useMachine(clipboard.machine, {
    id: useId(),
    value: "https://github.com/chakra-ui/zag",
  })

  const api = clipboard.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Copy this link</label>
      <div {...api.getControlProps()}>
        <input {...api.getInputProps()} />
        <button {...api.getTriggerProps()}>
          {api.copied ? <ClipboardCheck /> : <ClipboardCopyIcon />}
        </button>
      </div>
    </div>
  )
}
```


## Setting the value to copy

You can set the value to copy by passing a `value` prop to the `machine`
context.

```jsx {2}
const service = useMachine(clipboard.machine, {
  value: "Hello, world!",
})
```

## Listening to copy events

When the value is copied to the clipboard, the `onStatusChange` event is fired.
You can listen to this event and perform any action you want.

```jsx {2}
const service = useMachine(clipboard.machine, {
  onStatusChange: (details) => {
    console.log("Copy status changed to", details.copied)
  },
})
```

## Checking if the value is copied

Use the `api.copied` property to check if the value is copied to the clipboard.

```jsx {2}
const api = clipboard.connect(service)

if (api.copied) {
  console.log("Value is copied to the clipboard")
}
```

## Changing the timeout

By default, the clipboard machine will automatically reset the state to `idle`
after `3000ms`. You can change this timeout by passing a `timeout` option to the
`machine` context.

```jsx {2}
const service = useMachine(clipboard.machine, {
  timeout: 5000,
})
```

## Styling guide

Earlier, we mentioned that each clipboard part has a `data-part` attribute added
to them to select and style them in the DOM.

```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: `() => void`
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



# Collapsible

A collapsible is a component which expands and collapses a panel.

## Resources


[Latest version: v1.5.0](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

To use the collapsible machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/collapsible @zag-js/react
# or
yarn add @zag-js/collapsible @zag-js/react
```


This command will install the framework agnostic collapsible logic and the
reactive utilities for your framework of choice.

## Usage

First, import the collapsible package into your project

```jsx
import * as collapsible from "@zag-js/collapsible"
```

The collapsible package exports two key functions:

- `machine` — The state machine logic for the collapsible widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
collapsible machine in your project 🔥

```tsx
import * as collapsible from "@zag-js/collapsible"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId } from "react"

function Collapsible() {
  const service = useMachine(collapsible.machine, { id: useId() })

  const api = collapsible.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <button {...api.getTriggerProps()}>Collapse Trigger</button>
      <div {...api.getContentProps()}>Collape Content</div>
    </div>
  )
}
```


## 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 the `disabled` machine context property to `true` to disable the
collapsible.

```jsx {2}
const service = useMachine(collapsible.machine, {
  disabled: true,
})
```

## 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: 0;
  }
  to {
    height: var(--height);
  }
}

@keyframes collapse {
  from {
    height: var(--height);
  }
  to {
    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

Earlier, we mentioned that each collapsible part has a `data-part` attribute
added to them to select and style them in the DOM.

### Open and closed state

When a collapsible is expanded or collapsed, a `data-state` attribute is set on
the root, trigger and content elements. This attribute is removed when it is
closed.

```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 */
}
```

## 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.

**`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: `() => void`
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

**`Trigger`**

**`data-scope`**: collapsible
**`data-part`**: trigger
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled

## 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.



# Color Picker

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 `<input type=color>` experience and
provides a more customizable and consistent user experience.

## Resources


[Latest version: v1.5.0](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**

- Support for custom color area
- Support for RGBA, HSLA, HEX, and HSBA formats
- Support for channel inputs and sliders
- Support for mouse, touch, and keyboard interactions
- Support for form submission and reset events
- Support for named css colors

## Installation

To use the color picker machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/color-picker @zag-js/react
# or
yarn add @zag-js/color-picker @zag-js/react
```


This command will install the framework agnostic color picker logic and the
reactive utilities for your framework of choice.

## 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

First, import the color picker package into your project

```jsx
import * as colorPicker from "@zag-js/color-picker"
```

The color picker package exports these functions:

- `machine` — The state machine logic for the color picker widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.
- `parse` - The function that parses a color string to an Color object.

Next, import the required hooks and functions for your framework and use the
color picker machine in your project 🔥

```jsx
import * as colorPicker from "@zag-js/color-picker"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId } from "react"

function ColorPicker() {
  const service = useMachine(colorPicker.machine, {
    id: useId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = colorPicker.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Select Color: {api.valueAsString}</label>

      <input {...api.getHiddenInputProps()} />

      <div {...api.getControlProps()}>
        <button {...api.getTriggerProps()}>
          <div {...api.getTransparencyGridProps({ size: "10px" })} />
          <div {...api.getSwatchProps({ value: api.value })} />
        </button>
        <input {...api.getChannelInputProps({ channel: "hex" })} />
        <input {...api.getChannelInputProps({ channel: "alpha" })} />
      </div>

      <div {...api.getPositionerProps()}>
        <div {...api.getContentProps()}>
          <div {...api.getAreaProps()}>
            <div {...api.getAreaBackgroundProps()} />
            <div {...api.getAreaThumbProps()} />
          </div>

          <div {...api.getChannelSliderProps({ channel: "hue" })}>
            <div {...api.getChannelSliderTrackProps({ channel: "hue" })} />
            <div {...api.getChannelSliderThumbProps({ channel: "hue" })} />
          </div>

          <div {...api.getChannelSliderProps({ channel: "alpha" })}>
            <div {...api.getTransparencyGridProps({ size: "12px" })} />
            <div {...api.getChannelSliderTrackProps({ channel: "alpha" })} />
            <div {...api.getChannelSliderThumbProps({ channel: "alpha" })} />
          </div>
        </div>
      </div>
    </div>
  )
}
```


## Setting the initial value

To set the initial value of the color picker, use the `value` context property.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  defaultValue: colorPicker.parse("#ff0000"),
})
```

## 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 }
  },
})
```

> When using the `onValueChange` method in React.js, you might need to use the
> `flushSync` method from `react-dom` to ensure the value is updated in sync

## 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` by using the `format` context property.

When this property 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 }
  },
})
```

## Showing color presets

Adding color presets in form of swatches can help users pick colors faster. To
support this, use the `getSwatchTriggerProps(...)` and `getSwatchProps(...)` to
get the props needed to show the swatches buttons.

```tsx {18-31}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: useId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = colorPicker.connect(service, normalizeProps)

  const presets = ["#ff0000", "#00ff00", "#0000ff"]

  return (
    <div {...api.getRootProps()}>
      {/* ... */}
      <div {...api.getPositionerProps()}>
        <div {...api.getContentProps()}>
          <div {...api.getSwatchGroupProps()}>
            {presets.map((preset) => (
              <button
                key={preset}
                {...api.getSwatchTriggerProps({ value: preset })}
              >
                <div style={{ position: "relative" }}>
                  <div {...api.getTransparencyGridProps({ size: "4px" })} />
                  <div {...api.getSwatchProps({ value: preset })} />
                </div>
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  )
}
```


## Disabling the color picker

To disable user interactions with the color picker, set the `disabled` context
property to `true`.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  disabled: true,
})
```

## Controlling the open and closed state

To control the open and closed state of the color picker, use the `open` and
`onOpenChange` context properties.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  open: true,
  onOpenChange: (details) => {
    // details => { open: boolean }
  },
})
```

You can also leverage the `api.setOpen(...)` method to control the open and
closed state of the color picker.

## 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.

```tsx {16-38}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: useId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = colorPicker.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {/* ... */}
      <div {...api.getPositionerProps()}>
        <div {...api.getContentProps()}>
          {api.format === "rgba" && (
            <div>
              <div>
                <span>R</span>
                <input {...api.getChannelInputProps({ channel: "red" })} />
              </div>

              <div>
                <span>G</span>
                <input {...api.getChannelInputProps({ channel: "green" })} />
              </div>

              <div>
                <span>B</span>
                <input {...api.getChannelInputProps({ channel: "blue" })} />
              </div>

              <div>
                <span>A</span>
                <input {...api.getChannelInputProps({ channel: "alpha" })} />
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  )
}
```


## 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 the `api.value`

```tsx {13-16}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: useId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = colorPicker.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div>
        <div {...api.getTransparencyGridProps({ size: "4px" })} />
        <div {...api.getSwatchProps({ value: api.value })} />
      </div>
      {/* ... */}
    </div>
  )
}
```


> 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 allows a user 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

```tsx {16-18}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: useId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = colorPicker.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {/* ... */}
      <div {...api.getPositionerProps()}>
        <div {...api.getContentProps()}>
          <button {...api.getEyeDropperTriggerProps()}>
            <EyeDropIcon />
          </button>
        </div>
      </div>
    </div>
  )
}
```


## Usage within forms

To use the color picker within a form, add the `name` context property to the
machine and render the visually hidden input using the `hiddenInputProps`.

```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; }>`
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

**`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

**`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-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-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

## Accessibility

### Keyboard Interactions

**`Enter`**
Description: <span>When focus is on the trigger, opens the color picker<br />When focus is on a trigger of a swatch, selects the color (and closes the color picker)<br />When focus is on the input or channel inputs, selects the color</span>

**`ArrowLeft`**
Description: <span>When focus is on the color area, decreases the hue value of the color<br />When focus is on the channel sliders, decreases the value of the channel</span>

**`ArrowRight`**
Description: <span>When focus is on the color area, increases the hue value of the color<br />When focus is on the channel sliders, increases the value of the channel</span>

**`ArrowUp`**
Description: <span>When focus is on the color area, increases the saturation value of the color<br />When focus is on the channel sliders, increases the value of the channel</span>

**`ArrowDown`**
Description: <span>When focus is on the color area, decreases the saturation value of the color<br />When focus is on the channel sliders, decreases the value of the channel</span>

**`Esc`**
Description: Closes the color picker and moves focus to the trigger



# Combobox

A combobox is an input widget with an associated popup that enables users to
select a value from a collection of possible values.

## Resources


[Latest version: v1.5.0](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**

- Support for selecting multiple values
- Support for disabled options
- Support for custom user input values
- Support for mouse, touch, and keyboard interactions
- Keyboard support for opening the combo box list box using the arrow keys,
  including automatically focusing the first or last item accordingly

## Installation

To use the combobox machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/combobox @zag-js/react
# or
yarn add @zag-js/combobox @zag-js/react
```


This command will install the framework agnostic combobox logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the combobox 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

First, import the combobox package into your project

```jsx
import * as combobox from "@zag-js/combobox"
```

The combobox package exports these functions:

- `machine` — The state machine logic for the combobox widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.
- `collection` - The function that creates a
  [collection interface](/overview/collection) from an array of items.

Next, import the required hooks and functions for your framework and use the
combobox machine in your project 🔥

```jsx
import * as combobox from "@zag-js/combobox"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useState, useId } from "react"

const comboboxData = [
  { label: "Zambia", code: "ZA" },
  { label: "Benin", code: "BN" },
  //...
]

export function Combobox() {
  const [options, setOptions] = useState(comboboxData)

  const collection = combobox.collection({
    items: options,
    itemToValue: (item) => item.code,
    itemToString: (item) => item.label,
  })

  const service = useMachine(combobox.machine, {
    id: useId(),
    collection,
    onOpenChange() {
      setOptions(comboboxData)
    },
    onInputValueChange({ inputValue }) {
      const filtered = comboboxData.filter((item) =>
        item.label.toLowerCase().includes(inputValue.toLowerCase()),
      )
      setOptions(filtered.length > 0 ? filtered : comboboxData)
    },
  })

  const api = combobox.connect(service, normalizeProps)

  return (
    <div>
      <div {...api.getRootProps()}>
        <label {...api.getLabelProps()}>Select country</label>
        <div {...api.getControlProps()}>
          <input {...api.getInputProps()} />
          <button {...api.getTriggerProps()}>â–¼</button>
        </div>
      </div>
      <div {...api.getPositionerProps()}>
        {options.length > 0 && (
          <ul {...api.getContentProps()}>
            {options.map((item) => (
              <li key={item.code} {...api.getItemProps({ item })}>
                {item.label}
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  )
}
```


## Setting the initial value

To set the initial value of the combobox, pass the `value` property to the
machine's context.

> The `value` property must be an array of strings. If selecting a single value,
> pass an array with a single string.

```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"],
})
```

## Selecting multiple values

To allow selecting multiple values, set the `multiple` property in the machine's
context to `true`.

```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, the selected values of a combobox are displayed in the input
element, when selecting multiple items, it is a better UX to render the selected
value outside the combobox.

To achieve this you need to:

- 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

To make a combobox disabled, set the context's `disabled` property to `true`

```jsx {2}
const service = useMachine(combobox.machine, {
  disabled: true,
})
```

## Disabling an option

To make a combobox option disabled, pass the `isItemDisabled` property to the
collection function.

```jsx {6-8}
const service = useMachine(combobox.machine, {
  id: useId(),
  collection: combobox.collection({
    items: countries,
    isItemDisabled(item) {
      return item.disabled
    },
  }),
})
```

## Close on select

This behaviour ensures that the menu is closed when an option is selected and is
`true` by default. It's only concerned with when an option is selected with
pointer or enter key. To disable the behaviour, set the `closeOnSelect` property
in the machine's context to `false`.

```jsx {2}
const service = useMachine(combobox.machine, {
  closeOnSelect: false,
})
```

## Making the combobox readonly

To make a combobox readonly, set the context's `readOnly` property to `true`

```jsx {2}
const service = useMachine(combobox.machine, {
  readOnly: true,
})
```

## Listening for highlight changes

When an option is highlighted with the pointer or keyboard, use the
`onHighlightChange` property to listen for this change and do something with it.

```jsx {3-6}
const service = useMachine(combobox.machine, {
  id: useId(),
  onHighlightChange(details) {
    // details => { value: string | null; item: CollectionItem | null }
    console.log(details)
  },
})
```

## Listening for value changes

When an item is selected, use `onValueChange` property to listen for this change
and do something with it.

```jsx {3-6}
const service = useMachine(combobox.machine, {
  onValueChange(details) {
    // details => { value: string[]; items: CollectionItem[] }
    console.log(details)
  },
})
```

## Usage within forms

The combobox works when placed within a form and the form is submitted. We
achieve this by:

- ensuring we emit the input event as the value changes.
- adding a `name` attribute to the input so the value can be accessed in the
  `FormData`.

To get this feature working you need to pass a `name` option to the context.

```jsx {2}
const service = useMachine(combobox.machine, {
  name: "countries",
})
```

## Allowing custom values

By default, the combobox only allows selecting values from the collection. To
allow custom values, set the `allowCustomValue` property in the machine's
context to `true`.

```jsx {2}
const service = useMachine(combobox.machine, {
  allowCustomValue: true,
})
```

## Styling guide

Earlier, we mentioned that each combobox part has a `data-part` attribute added
to them to select and style them in the DOM.

### Open and closed state

When the combobox is open or closed, the `data-state` attribute is added to the
content,control, input and control parts.

```css
[data-part="control"][data-state="open|closed"] {
  /* styles for control open or state */
}

[data-part="input"][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 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-selected` 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

**`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<T>) => void`
Description: Function called when a new item is selected

**`onHighlightChange`**
Type: `(details: HighlightChangeDetails<T>) => void`
Description: Function called when an item is highlighted using the pointer
or keyboard navigation.

**`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<T>`
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

**`syncSelectedItems`**
Type: `() => void`
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: `() => void`
Description: Function to focus on the combobox input

**`setInputValue`**
Type: `(value: string) => 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) => void`
Description: Function to open or close the combobox

**`collection`**
Type: `ListCollection<V>`
Description: Function to toggle the combobox

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => 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-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-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-placement`**: The placement of the content

**`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"

## 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



# Date Picker

A datepicker allows users to enter a date either through text input, or by
choosing a date from the calendar.

> **Good to know**: The date picker machine is built around the
> [ISO 8601 date format](https://www.iso.org/iso-8601-date-and-time-format.html)

## Resources


[Latest version: v1.5.0](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
- Support for date range selection
- Support for disabling specific dates
- Localization support
- Provides keyboard accessibility for navigating the calendar.

## Installation

To use the date-picker machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/date-picker @zag-js/react
# or
yarn add @zag-js/date-picker @zag-js/react
```


This command will install the framework agnostic date-picker logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the date-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

First, import the date picker package into your project

```jsx
import * as datepicker from "@zag-js/date-picker"
```

The date picker package exports these key functions:

- `machine` — The state machine logic for the date-picker widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.
- `parse` - The function that parses the date string into a date object. This
  function uses
  [`@internationalized/date`](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html)
  under the hood.

> 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.

Next, import the required hooks and functions for your framework and use the
date-picker machine in your project 🔥

```jsx
import * as datepicker from "@zag-js/date-picker"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import { useId } from "react"

function DatePicker() {
  const service = useMachine(datepicker.machine, { id: useId() })

  const api = datepicker.connect(service, normalizeProps)

  return (
    <>
      <div {...api.getControlProps()}>
        <input {...api.getInputProps()} />
        <button {...api.getTriggerProps()}>🗓</button>
      </div>

      <Portal>
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>
            {/*  Day View  */}
            <div hidden={api.view !== "day"}>
              <div {...api.getViewControlProps({ view: "year" })}>
                <button {...api.getPrevTriggerProps()}>Prev</button>
                <button {...api.getViewTriggerProps()}>
                  {api.visibleRangeText.start}
                </button>
                <button {...api.getNextTriggerProps()}>Next</button>
              </div>

              <table {...api.getTableProps({ view: "day" })}>
                <thead {...api.getTableHeaderProps({ view: "day" })}>
                  <tr {...api.getTableRowProps({ view: "day" })}>
                    {api.weekDays.map((day, i) => (
                      <th scope="col" key={i} aria-label={day.long}>
                        {day.narrow}
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody {...api.getTableBodyProps({ view: "day" })}>
                  {api.weeks.map((week, i) => (
                    <tr key={i} {...api.getTableRowProps({ view: "day" })}>
                      {week.map((value, i) => (
                        <td key={i} {...api.getDayTableCellProps({ value })}>
                          <div {...api.getDayTableCellTriggerProps({ value })}>
                            {value.day}
                          </div>
                        </td>
                      ))}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {/*  Month View  */}
            <div hidden={api.view !== "month"}>
              <div {...api.getViewControlProps({ view: "month" })}>
                <button {...api.getPrevTriggerProps({ view: "month" })}>
                  Prev
                </button>
                <button {...api.getViewTriggerProps({ view: "month" })}>
                  {api.visibleRange.start.year}
                </button>
                <button {...api.getNextTriggerProps({ view: "month" })}>
                  Next
                </button>
              </div>

              <table {...api.getTableProps({ view: "month", columns: 4 })}>
                <tbody {...api.getTableBodyProps({ view: "month" })}>
                  {api
                    .getMonthsGrid({ columns: 4, format: "short" })
                    .map((months, row) => (
                      <tr key={row} {...api.getTableRowProps()}>
                        {months.map((month, index) => (
                          <td
                            key={index}
                            {...api.getMonthTableCellProps({
                              ...month,
                              columns: 4,
                            })}
                          >
                            <div
                              {...api.getMonthTableCellTriggerProps({
                                ...month,
                                columns: 4,
                              })}
                            >
                              {month.label}
                            </div>
                          </td>
                        ))}
                      </tr>
                    ))}
                </tbody>
              </table>
            </div>

            {/*  Year View  */}
            <div hidden={api.view !== "year"}>
              <div {...api.getViewControlProps({ view: "year" })}>
                <button {...api.getPrevTriggerProps({ view: "year" })}>
                  Prev
                </button>
                <span>
                  {api.getDecade().start} - {api.getDecade().end}
                </span>
                <button {...api.getNextTriggerProps({ view: "year" })}>
                  Next
                </button>
              </div>

              <table {...api.getTableProps({ view: "year", columns: 4 })}>
                <tbody {...api.getTableBodyProps()}>
                  {api.getYearsGrid({ columns: 4 }).map((years, row) => (
                    <tr key={row} {...api.getTableRowProps({ view: "year" })}>
                      {years.map((year, index) => (
                        <td
                          key={index}
                          {...api.getYearTableCellProps({
                            ...year,
                            columns: 4,
                          })}
                        >
                          <div
                            {...api.getYearTableCellTriggerProps({
                              ...year,
                              columns: 4,
                            })}
                          >
                            {year.label}
                          </div>
                        </td>
                      ))}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </Portal>
    </>
  )
}
```


## Setting the initial date

To set the initial value that is rendered by the date picker, set the `value`
property in the machine context.

```jsx
const service = useMachine(datepicker.machine, {
  defaultValue: [datepicker.parse("2022-01-01")],
})
```

## Controlling the selected date

Use the `api.setValue` method to control the selected date in the DatePicker
component.

```jsx
// parse the date string into a date object
const nextValue = datepicker.parse("2022-01-01")

// set the new value
api.setValue(nextValue)
```

> Alternatively, you can also use the `value` and `onValueChange` callbacks to
> programmatically control the selected date.

## Controlling the open state

To manage the open state of the datepicker's dialog, we recommended using
`api.setOpen` method.

```jsx
// open the date picker
api.setOpen(true)

// close the date picker
api.setOpen(false)
```

> Alternatively, you can also use the `open` and `onOpenChange` callbacks to
> programmatically control the open state.

## Setting the min and max dates

To constrain the date range that can be selected by the user, set the `min` and
`max` properties in the machine context.

```jsx
const service = useMachine(datepicker.machine, {
  min: datepicker.parse("2022-01-01"),
  max: datepicker.parse("2022-12-31"),
})
```

When the min or max date value is reached, the next and prev triggers will be
disabled.

## Changing the start of the week

Set the `startOfWeek` property in the machine context to change the start of the
week. The property accepts a number from `0` to `6`, where `0` is Sunday and `6`
is Saturday.

```jsx
const service = useMachine(datepicker.machine, {
  startOfWeek: 1, // Monday
})
```

## Disabling the date picker

To disable the date picker, set the `disabled` property in the machine context
to `true`.

```jsx
const service = useMachine(datepicker.machine, {
  disabled: true,
})
```

## Rendering month and year pickers

To render the month and year pickers, use the `api.getMonthSelectProps` and
`api.getYearSelectProps` prop getters.

```jsx
<div>
  <select {...api.getMonthSelectProps()}>
    {api.getMonths().map((month, i) => (
      <option key={i} value={month.value}>
        {month.label}
      </option>
    ))}
  </select>

  <select {...api.getYearSelectProps()}>
    {getYearsRange({ from: 1_000, to: 4_000 }).map((year, i) => (
      <option key={i} value={year}>
        {year}
      </option>
    ))}
  </select>
</div>
```

## Marking unavailable dates

To mark specific dates as unavailable, set the `isDateUnavailable` function in
the machine context. This function should return `true` for dates that are
unavailable.

```jsx
const service = useMachine(datepicker.machine, {
  isDateUnavailable: (date, locale) => {
    // mark weekends as unavailable
    return date.day === 0 || date.day === 6
  },
})
```

You can also leverage the numerous helpers from
[`@internationalized/date`](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html)
to create more complex date availability rules.

```jsx
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 calendar view is set to `day` by default. To change the starting view of the
calendar, set the `view` property in the machine context to either `day`,
`month`, or `year`.

```jsx
const service = useMachine(datepicker.machine, {
  view: "month",
})
```

## Setting the read-only mode

Set the `readOnly` property in the machine context to `true` to make the date
picker read-only. This means that users can't change the selected date.

```jsx
const service = useMachine(datepicker.machine, {
  readOnly: true,
})
```

## Setting the focused date

The datepicker's focused date is set to either the first selected date or
today's date by default.

To change the focused date, set the `focusedDate` property in the machine
context.

```jsx
const service = useMachine(datepicker.machine, {
  focusedDate: datepicker.parse("2022-01-01"),
})
```

## Rendering the calendar inline

To render the calendar inline, we recommended setting the `open` property to
`true` and `closeOnSelect` to `false`.

```jsx
const service = useMachine(datepicker.machine, {
  open: true,
  closeOnSelect: false,
})
```

## Usage within a form

To use the date picker within a form, set the `name` property in the machine
context. This property is used to identify the date picker in the form data.

```jsx
const service = useMachine(datepicker.machine, {
  name: "date",
})
```

## Rendering fixed number of weeks

The datepicker's calendar will render the weeks needed to display all of the
days in the month. Sometimes this can result in a jump in the UI when navigating
between different sized months (e.g., February vs. March).

To ensure the calendar renders the maximum number of weeks (6), you can set the
`fixedWeeks` prop to `true`.

```jsx
const service = useMachine(datepicker.machine, {
  fixedWeeks: true,
})
```

## Listening to date changes

To listen to date changes, use the `onValueChange` callback in the machine
context.

```jsx
const service = useMachine(datepicker.machine, {
  onValueChange(details) {
    // details => { value: DateValue[], valueAsString: string[], view: string }
    console.log("selected date:", details.valueAsString)
  },
})
```

## Listening to view changes

When the calendar view changes by click on the view controls, the `onViewChange`
callback is invoked.

```jsx
const service = useMachine(datepicker.machine, {
  onViewChange(details) {
    // details => { view: string }
    console.log("view changed to:", details.view)
  },
})
```

## Styling guide

Earlier, we mentioned that each date-picker part has a `data-part` attribute
added to them to select and style them in the DOM.

```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.

**`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; 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.

**`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`.

**`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.

**`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.

**`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

**`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.

**`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

**`view`**
Type: `DateView`
Description: The current view of the date picker

**`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: `() => void`
Description: Sets the selected date to today.

**`setValue`**
Type: `(values: CalendarDate[]) => void`
Description: Sets the selected date to the given date.

**`setFocusedValue`**
Type: `(value: CalendarDate) => void`
Description: Sets the focused date to the given date.

**`clearValue`**
Type: `() => 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<number>`
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: CalendarDate, 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: `() => void`
Description: Goes to the next month/year/decade.

**`goToPrev`**
Type: `() => void`
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.



# Dialog

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.5.0](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

To use the dialog machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/dialog @zag-js/react
# or
yarn add @zag-js/dialog @zag-js/react
```


This command will install the framework agnostic dialog logic and the reactive
utilities for your framework of choice.

## 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

First, import the dialog package into your project

```jsx
import * as dialog from "@zag-js/dialog"
```

The dialog package exports two key functions:

- `machine` — The state machine logic for the dialog widget as described in
  WAI-ARIA specification.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
dialog machine in your project 🔥

```tsx
import * as dialog from "@zag-js/dialog"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"

export function Dialog() {
  const service = useMachine(dialog.machine, { id: "1" })

  const api = dialog.connect(service, normalizeProps)

  return (
    <>
      <button {...api.getTriggerProps()}>Open Dialog</button>
      {api.open && (
        <Portal>
          <div {...api.getBackdropProps()} />
          <div {...api.getPositionerProps()}>
            <div {...api.getContentProps()}>
              <h2 {...api.getTitleProps()}>Edit profile</h2>
              <p {...api.getDescriptionProps()}>
                Make changes to your profile here. Click save when you are done.
              </p>
              <div>
                <input placeholder="Enter name..." />
                <button>Save</button>
              </div>
              <button {...api.getCloseTriggerProps()}>Close</button>
            </div>
          </div>
        </Portal>
      )}
    </>
  )
}
```


## Managing focus within the dialog

When the dialog opens, it automatically sets focus on the first focusable
elements and traps focus within it, so that tabbing is constrained to it.

To control the element that should receive focus on open, pass the
`initialFocusEl` context (which can be an element or a function that returns an
element)

```jsx {3,7,15}
export function Dialog() {
  // initial focused element ref
  const inputRef = useRef(null)

  const service = useMachine(dialog.machine, {
    initialFocusEl: () => inputRef.current,
  })

  // ...

  return (
    //...
    <input ref={inputRef} />
    // ...
  )
}
```


To set the element that receives focus when the dialog closes, pass the
`finalFocusEl` in the similar fashion as shown above.

## 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` context and calling `event.preventDefault()`

```jsx {2-7}
const service = useMachine(dialog.machine, {
  onInteractOutside(event) {
    const target = event.target
    if (target?.closest("<selector>")) {
      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)
  },
})
```

## Controlling the scroll behavior

When the dialog is open, it prevents scrolling on the `body` element. To disable
this behavior, set the `preventScroll` context to `false`.

```jsx {2}
const service = useMachine(dialog.machine, {
  preventScroll: false,
})
```

## Creating an alert dialog

The dialog has support for dialog and alert dialog roles. It's set to `dialog`
by default. To change it's role, pass the `role: alertdialog` property to the
machine's context.

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
> recommended setting focus to the least destructive action via `initialFocusEl`

## Styling guide

Earlier, we mentioned that each accordion part has a `data-part` attribute added
to them to select and style them in the DOM.

```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 */
}
```

## 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

**`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"

## 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

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 then edit interaction is
triggered (click, focus, or double-click).

## Resources


[Latest version: v1.5.0](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

To use the editable machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/editable @zag-js/react
# or
yarn add @zag-js/editable @zag-js/react
```


This command will install the framework agnostic editable logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the editable 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

First, import the editable package into your project

```jsx
import * as editable from "@zag-js/editable"
```

The editable package exports two key functions:

- `machine` — The state machine logic for the editable widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
editable machine in your project 🔥

```jsx
import * as editable from "@zag-js/editable"
import { useMachine, normalizeProps } from "@zag-js/react"

export default function Editable() {
  const service = useMachine(editable.machine, { id: "1" })

  const api = editable.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getAreaProps()}>
        <input {...api.getInputProps()} />
        <span {...api.getPreviewProps()} />
      </div>
    </div>
  )
}
```


## Setting the initial value

To set the initial value of the editable, pass the `value` property to the
machine's context.

```jsx {2}
const service = useMachine(editable.machine, {
  defaultValue: "Hello World",
})
```

## Listening for value changes

The editable machine 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)
  },
})
```

## 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.

```jsx
import * as editable from "@zag-js/editable"
import { useMachine } from "@zag-js/react"

export default function Editable() {
  const service = useMachine(editable.machine, { id: "1" })

  const api = editable.connect(service)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getAreaProps()}>
        <input {...api.getInputProps()} />
        <span {...api.getPreviewProps()} />
      </div>
      <div>
        {!api.editing && <button {...api.getEditTriggerProps()}>Edit</button>}
        {api.editing && (
          <div>
            <button {...api.getSubmitTriggerProps()}>Save</button>
            <button {...api.getCancelTriggerProps()}>Cancel</button>
          </div>
        )}
      </div>
    </div>
  )
}
```


## Auto-resizing the editable

To auto-grow the editable as the content changes, pass the `autoResize: true`
property to the machine's context.

```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 its shared by the input and preview elements.

### Setting a maxWidth

It is a common pattern to set a maximum of the editable as it auto-grows. To
achieve this, set the `maxWidth` property of the machine's context to the
desired value.

```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.

To change the mode to "double-click", set the `activationMode: 'dblclick'`
property in the machine's context.

```jsx {2}
const service = useMachine(editable.machine, {
  activationMode: "dblclick",
})
```

## Usage with Textarea

The editable machine 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 the `api.inputProps` to spread the input props to the textarea element.
> You might need to cast the input props to the correct type.

```tsx {2}
<textarea {...(api.inputProps as HTMLTextareaProps<HTMLTextareaElement>)} />
```

## Styling guide

Earlier, we mentioned that each editable part has a `data-part` attribute added
to them to select and style them in the DOM.

### Focused state

When the editable is in the focused mode, we set a `data-focus` attribute on the
"area" part.

```css
[data-part="area"][data-focus] {
  /* CSS for the editable's focus state */
}
```

### Empty state

When the editable's value is empty, we set a `data-empty` attribute on the
"area" part.

```css
[data-part="area"][data-empty] {
  /* CSS for the editable's focus state */
}
```

### Disabled state

When the editable is disabled, we set a `data-disabled` attribute on the "area"
part.

```css
[data-part="area"][data-disabled] {
  /* CSS for the editable's focus state */
}
```

## Methods and Properties

### Machine Context

The editable machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; area: string; label: string; preview: string; input: string; control: string; submitTrigger: string; cancelTrigger: string; editTrigger: string; }>`
Description: The ids of the elements in the editable. Useful for composition.

**`invalid`**
Type: `boolean`
Description: Whether the input's value is invalid.

**`name`**
Type: `string`
Description: The name attribute of the editable component. Used for form submission.

**`form`**
Type: `string`
Description: The associate form of the underlying input.

**`autoResize`**
Type: `boolean`
Description: Whether the editable should auto-resize to fit the content.

**`activationMode`**
Type: `ActivationMode`
Description: The activation mode for the preview element.

- "focus" - Enter edit mode when the preview is focused
- "dblclick" - Enter edit mode when the preview is double-clicked
- "click" - Enter edit mode when the preview is clicked

**`submitMode`**
Type: `SubmitMode`
Description: The action that triggers submit in the edit mode:

- "enter" - Trigger submit when the enter key is pressed
- "blur" - Trigger submit when the editable is blurred
- "none" - No action will trigger submit. You need to use the submit button
- "both" - Pressing `Enter` and blurring the input will trigger submit

**`selectOnFocus`**
Type: `boolean`
Description: Whether to select the text in the input when it is focused.

**`edit`**
Type: `boolean`
Description: Whether the editable is in edit mode.

**`defaultEdit`**
Type: `boolean`
Description: Whether the editable is in edit mode by default.

**`onEditChange`**
Type: `(details: EditChangeDetails) => void`
Description: Function to call when the edit mode changes.

**`maxLength`**
Type: `number`
Description: The maximum number of characters allowed in the editable

**`disabled`**
Type: `boolean`
Description: Whether the editable is disabled.

**`readOnly`**
Type: `boolean`
Description: Whether the editable is read-only.

**`required`**
Type: `boolean`
Description: Whether the editable is required.

**`placeholder`**
Type: `string | { edit: string; preview: string; }`
Description: The placeholder text for the editable.

**`translations`**
Type: `IntlTranslations`
Description: The translations for the editable.

**`finalFocusEl`**
Type: `() => HTMLElement`
Description: The element to receive focus when the editable is closed.

**`value`**
Type: `string`
Description: The controlled value of the editable.

**`defaultValue`**
Type: `string`
Description: The initial value of the editable when rendered.
Use when you don't need to control the value of the editable.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function to call when the value changes.

**`onValueRevert`**
Type: `(details: ValueChangeDetails) => void`
Description: Function to call when the value is reverted.

**`onValueCommit`**
Type: `(details: ValueChangeDetails) => void`
Description: Function to call when the value is committed.

**`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.

**`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 editable `api` exposes the following methods:

**`editing`**
Type: `boolean`
Description: Whether the editable is in edit mode

**`empty`**
Type: `boolean`
Description: Whether the editable value is empty

**`value`**
Type: `string`
Description: The current value of the editable

**`valueText`**
Type: `string`
Description: The current value of the editable, or the placeholder if the value is empty

**`setValue`**
Type: `(value: string) => void`
Description: Function to set the value of the editable

**`clearValue`**
Type: `() => void`
Description: Function to clear the value of the editable

**`edit`**
Type: `() => void`
Description: Function to enter edit mode

**`cancel`**
Type: `() => void`
Description: Function to exit edit mode, and discard any changes

**`submit`**
Type: `() => void`
Description: Function to exit edit mode, and submit any changes

### Data Attributes

**`Area`**

**`data-scope`**: editable
**`data-part`**: area
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled
**`data-placeholder-shown`**: Present when placeholder is shown

**`Label`**

**`data-scope`**: editable
**`data-part`**: label
**`data-focus`**: Present when focused
**`data-invalid`**: Present when invalid

**`Input`**

**`data-scope`**: editable
**`data-part`**: input
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid
**`data-autoresize`**: 

**`Preview`**

**`data-scope`**: editable
**`data-part`**: preview
**`data-placeholder-shown`**: Present when placeholder is shown
**`data-readonly`**: Present when read-only
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-autoresize`**: 

## Accessibility

### Keyboard Interactions

**`Enter`**
Description: Saves the edited content and exits edit mode.

**`Escape`**
Description: Discards the changes and exits edit mode.



# File Upload

File upload component is used to upload multiple files.

The native input file element is quite difficult to style and doesn't provide a
drag-n-drop version.

> The file upload component doesn't handle the actual file uploading process. It
> only handles the UI and the state of the file upload.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/file-upload)
[Logic Visualizer](https://zag-visualizer.vercel.app/file-upload)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/file-upload)



**Features**

- Supports a button to open the file dialog.
- Supports drag and drop to upload files.
- Set the maximum number of files that can be uploaded.
- Set the maximum size of the files that can be uploaded.
- Set the accepted file types.

## Installation

To use the file upload machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/file-upload @zag-js/react
# or
yarn add @zag-js/file-upload @zag-js/react
```


This command will install the framework agnostic file upload logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the file upload 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

First, import the file upload package into your project

```jsx
import * as fileUpload from "@zag-js/file-upload"
```

The file upload package exports two key functions:

- `machine` — The state machine logic for the file upload widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
file upload machine in your project 🔥

```jsx
import * as fileUpload from "@zag-js/file-upload"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId } from "react"

export function FileUpload() {
  const service = useMachine(fileUpload.machine, {
    id: useId(),
  })

  const api = fileUpload.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getDropzoneProps()}>
        <input {...api.getHiddenInputProps()} />
        <span>Drag your file(s) here</span>
      </div>

      <button {...api.getTriggerProps()}>Choose file(s)</button>

      <ul {...api.getItemGroupProps()}>
        {api.acceptedFiles.map((file) => (
          <li key={file.name} {...api.getItemProps({ file })}>
            <div {...api.getItemNameProps({ file })}>{file.name}</div>
            <button {...api.getItemDeleteTriggerProps({ file })}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  )
}
```


## Setting the accepted file types

Use the `accept` attribute to set the accepted file types.

```jsx
const service = useMachine(fileUpload.machine, {
  accept: "image/*",
})
```

Alternatively, you can provide an object with a MIME type and an array of file
extensions.

```jsx
const service = useMachine(fileUpload.machine, {
  accept: {
    "image/png": [".png"],
    "text/html": [".html", ".htm"],
  },
})
```

## Setting the maximum number of files

Use the `maxFiles` attribute to set the maximum number of files that can be
uploaded. This will set the `multiple` attribute on the underlying input
element.

```jsx
const service = useMachine(fileUpload.machine, {
  maxFiles: 5,
})
```

## Setting the maximum size per file

Use the `maxFileSize` attribute to set the maximum size per file that can be
uploaded.

```jsx
const service = useMachine(fileUpload.machine, {
  maxFileSize: 1024 * 1024 * 10, // 10MB
})
```

## Listening to file changes

When files are uploaded, the `onFileChange` callback is invoked with the details
of the accepted and rejected files.

```jsx
const service = useMachine(fileUpload.machine, {
  onFileChange(details) {
    // details => { acceptedFiles: File[], rejectedFiles: { file: File, errors: [] }[] }
    console.log(details.acceptedFiles)
    console.log(details.rejectedFiles)
  },
})
```

## Usage within a form

To use the file upload within a form, set the `name` attribute in the machine's
context, and ensure you render the input element `api.getHiddenInputProps()`

```jsx
const service = useMachine(fileUpload.machine, {
  name: "avatar",
})
```

## Displaying image preview

To display a preview of the uploaded image, use the built-in FileReader API to
read the file and set the `src` attribute of an image element.

```jsx
const service = useMachine(fileUpload.machine, {
  onFileChange(details) {
    const reader = new FileReader()
    reader.onload = (event) => {
      const image = event.target.result
      // set the image as the src of an image element
    }
    reader.readAsDataURL(details.acceptedFiles[0])
  },
})
```

## Applying custom validation

To apply custom validation, set the `validate` attribute to a function that
returns an **array of error strings**.

The returned array can contain any string as an error message. While zagjs
supports default errors such as `TOO_MANY_FILES`, `FILE_INVALID_TYPE`,
`FILE_TOO_LARGE`, or `FILE_TOO_SMALL`, you can return any string that represents
your custom validation errors.

> Return `null` if no validation errors are detected.

```jsx
const service = useMachine(fileUpload.machine, {
  validate(file) {
    // Check if file size exceeds 10MB
    if (file.size > 1024 * 1024 * 10) {
      return ["FILE_TOO_LARGE"]
    }
    return null
  },
})
```

Apply multiple validation errors:

```js
const service = useMachine(fileUpload.machine, {
  validate(file) {
    const errors = []

    // Check file size
    if (file.size > 10 * 1024 * 1024) {
      errors.push("FILE_TOO_LARGE") // Default error enum
    }

    // Ensure file is a PDF
    if (!file.name.endsWith(".pdf")) {
      errors.push("ONLY_PDF_ALLOWED") // Custom error
    }

    // Custom check: Reject duplicate files
    const isDuplicate = details.acceptedFiles.some(
      (acceptedFile) => acceptedFile.name === file.name,
    )
    if (isDuplicate) {
      errors.push("FILE_EXISTS")
    }

    return errors.length > 0 ? errors : null
  },
})
```

## Disabling drag and drop

To disable the drag and drop functionality, set the `allowDrop` context property
to `false`.

```jsx
const service = useMachine(fileUpload.machine, {
  allowDrop: false,
})
```

## Allowing directory selection

Set the `directory` property to `true` to enable selecting directories instead
of files.

This maps to the native input `webkitdirectory` HTML attribute and allows users
to select directories and their contents.

> Please note that support for this feature varies from browser to browser.

```jsx
const service = useMachine(fileUpload.machine, {
  directory: true,
})
```

## Supporting media capture on mobile devices

Set the `capture` property to specify the media capture mechanism to capture
media on the spot. The value can be:

- `user` for capturing media from the user-facing camera
- `environment` for the outward-facing camera

> This behavior only works on mobile devices. On desktop devices, it will open
> the file system like normal.

```jsx
const service = useMachine(fileUpload.machine, {
  capture: "user",
})
```

## Pasting files from clipboard

After a user copies an image, to allow pasting the files from the clipboard, you
can listen for the paste event and use the `api.setFiles` method to set the
files.

Here's an example of how to do this in React.

```jsx
function Demo() {
  const service = useMachine(fileUpload.machine, {
    accept: "image/*",
  })

  const api = fileUpload.connect(service, normalizeProps)

  return (
    <textarea
      onPaste={(event) => {
        if (event.clipboardData?.files) {
          api.setFiles(Array.from(event.clipboardData.files))
        }
      }}
    />
  )
}
```

## Styling guide

Earlier, we mentioned that each file upload part has a `data-part` attribute
added to them to select and style them in the DOM.

```css
[data-part="root"] {
  /* styles for root element*/
}

[data-part="dropzone"] {
  /* styles for root element*/
}

[data-part="trigger"] {
  /* styles for file picker trigger */
}

[data-part="label"] {
  /* styles for the input's label */
}
```

### Dragging State

When the user drags a file over the file upload, the `data-dragging` attribute
is added to the `root` and `dropzone` parts.

```css
[data-part="root"][data-dragging] {
  /* styles for when the user is dragging a file over the file upload */
}

[data-part="dropzone"][data-dragging] {
  /* styles for when the user is dragging a file over the file upload */
}
```

### Disabled State

When the file upload is disabled, the `data-disabled` attribute is added to the
component parts.

```css
[data-part="root"][data-disabled] {
  /* styles for when the file upload is disabled */
}

[data-part="dropzone"][data-disabled] {
  /* styles for when the file upload is disabled */
}

[data-part="trigger"][data-disabled] {
  /* styles for when the file upload is disabled */
}

[data-part="label"][data-disabled] {
  /* styles for when the file upload is disabled */
}
```

## Methods and Properties

### Machine Context

The file upload machine exposes the following context properties:

**`name`**
Type: `string`
Description: The name of the underlying file input

**`ids`**
Type: `Partial<{ root: string; dropzone: string; hiddenInput: string; trigger: string; label: string; item(id: string): string; itemName(id: string): string; itemSizeText(id: string): string; itemPreview(id: string): string; }>`
Description: The ids of the elements. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: The localized messages to use.

**`accept`**
Type: `Record<string, string[]> | FileMimeType[]`
Description: The accept file types

**`disabled`**
Type: `boolean`
Description: Whether the file input is disabled

**`required`**
Type: `boolean`
Description: Whether the file input is required

**`allowDrop`**
Type: `boolean`
Description: Whether to allow drag and drop in the dropzone element

**`maxFileSize`**
Type: `number`
Description: The maximum file size in bytes

**`minFileSize`**
Type: `number`
Description: The minimum file size in bytes

**`maxFiles`**
Type: `number`
Description: The maximum number of files

**`preventDocumentDrop`**
Type: `boolean`
Description: Whether to prevent the drop event on the document

**`validate`**
Type: `(file: File, details: FileValidateDetails) => FileError[]`
Description: Function to validate a file

**`onFileChange`**
Type: `(details: FileChangeDetails) => void`
Description: Function called when the value changes, whether accepted or rejected

**`onFileAccept`**
Type: `(details: FileAcceptDetails) => void`
Description: Function called when the file is accepted

**`onFileReject`**
Type: `(details: FileRejectDetails) => void`
Description: Function called when the file is rejected

**`capture`**
Type: `"user" | "environment"`
Description: The default camera to use when capturing media

**`directory`**
Type: `boolean`
Description: Whether to accept directories, only works in webkit browsers

**`invalid`**
Type: `boolean`
Description: Whether the file input is invalid

**`locale`**
Type: `string`
Description: The current locale. Based on the BCP 47 definition.

**`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 file upload `api` exposes the following methods:

**`dragging`**
Type: `boolean`
Description: Whether the user is dragging something over the root element

**`focused`**
Type: `boolean`
Description: Whether the user is focused on the dropzone element

**`disabled`**
Type: `boolean`
Description: Whether the file input is disabled

**`openFilePicker`**
Type: `() => void`
Description: Function to open the file dialog

**`deleteFile`**
Type: `(file: File) => void`
Description: Function to delete the file from the list

**`acceptedFiles`**
Type: `File[]`
Description: The accepted files that have been dropped or selected

**`rejectedFiles`**
Type: `FileRejection[]`
Description: The files that have been rejected

**`setFiles`**
Type: `(files: File[]) => void`
Description: Function to set the value

**`clearFiles`**
Type: `() => void`
Description: Function to clear the value

**`clearRejectedFiles`**
Type: `() => void`
Description: Function to clear the rejected files

**`getFileSize`**
Type: `(file: File) => string`
Description: Function to format the file size (e.g. 1.2MB)

**`createFileUrl`**
Type: `(file: File, cb: (url: string) => void) => VoidFunction`
Description: Function to get the preview url of a file.
Returns a function to revoke the url.

**`setClipboardFiles`**
Type: `(dt: DataTransfer) => boolean`
Description: Function to set the clipboard files.
Returns `true` if the clipboard data contains files, `false` otherwise.

### Data Attributes

**`Root`**

**`data-scope`**: file-upload
**`data-part`**: root
**`data-disabled`**: Present when disabled
**`data-dragging`**: Present when in the dragging state

**`Dropzone`**

**`data-scope`**: file-upload
**`data-part`**: dropzone
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-dragging`**: Present when in the dragging state

**`Trigger`**

**`data-scope`**: file-upload
**`data-part`**: trigger
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid

**`ItemGroup`**

**`data-scope`**: file-upload
**`data-part`**: item-group
**`data-disabled`**: Present when disabled

**`Item`**

**`data-scope`**: file-upload
**`data-part`**: item
**`data-disabled`**: Present when disabled

**`ItemName`**

**`data-scope`**: file-upload
**`data-part`**: item-name
**`data-disabled`**: Present when disabled

**`ItemSizeText`**

**`data-scope`**: file-upload
**`data-part`**: item-size-text
**`data-disabled`**: Present when disabled

**`ItemPreview`**

**`data-scope`**: file-upload
**`data-part`**: item-preview
**`data-disabled`**: Present when disabled

**`ItemPreviewImage`**

**`data-scope`**: file-upload
**`data-part`**: item-preview-image
**`data-disabled`**: Present when disabled

**`ItemDeleteTrigger`**

**`data-scope`**: file-upload
**`data-part`**: item-delete-trigger
**`data-disabled`**: Present when disabled

**`Label`**

**`data-scope`**: file-upload
**`data-part`**: label
**`data-disabled`**: Present when disabled

**`ClearTrigger`**

**`data-scope`**: file-upload
**`data-part`**: clear-trigger
**`data-disabled`**: Present when disabled



# Hover Card

An hover card allows sighted users to preview content available behind a link

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/hover-card)
[Logic Visualizer](https://zag-visualizer.vercel.app/hover-card)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/hover-card)



**Features**

- Customize side, alignment, offsets
- Optionally render a pointing arrow.
- Supports custom open and close delays.
- Opens on hover only.
- Ignored by screen readers.

## Installation

To use the hover card machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/hover-card @zag-js/react
# or
yarn add @zag-js/hover-card @zag-js/react
```


This command will install the framework agnostic hover card logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the hover card 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

First, import the hover card package into your project

```jsx
import * as hoverCard from "@zag-js/hover-card"
```

The hover card package exports two key functions:

- `machine` — The state machine logic for the hover card widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
hover-card machine in your project 🔥

```jsx
import * as hoverCard from "@zag-js/hover-card"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"

function HoverCard() {
  const service = useMachine(hoverCard.machine, { id: "1" })

  const api = hoverCard.connect(service, normalizeProps)

  return (
    <>
      <a
        href="https://twitter.com/zag_js"
        target="_blank"
        {...api.getTriggerProps()}
      >
        Twitter
      </a>

      {api.open && (
        <Portal>
          <div {...api.getPositionerProps()}>
            <div {...api.getContentProps()}>
              <div {...api.getArrowProps()}>
                <div {...api.getArrowTipProps()} />
              </div>
              Twitter Preview
            </div>
          </div>
        </Portal>
      )}
    </>
  )
}
```


## Making it opened initially

To make an hover card open by default, set the context's `open` property to true

```jsx {2}
const service = useMachine(hoverCard.machine, {
  defaultOpen: true,
})
```

## Listening for open state changes

When the hover card is `opened` or `closed`, the `onOpenChange` callback is
invoked.

```jsx {2-5}
const service = useMachine(hoverCard.machine, {
  onOpenChange(details) {
    // details => { open: boolean }
    console.log("hovercard is:", details.open ? "opened" : "closed")
  },
})
```

## Styling guide

Earlier, we mentioned that each hover card part has a `data-part` attribute
added to them to select and style them in the DOM.

```css
[data-part="trigger"] {
  /* styles for trigger */
}

[data-part="content"] {
  /* styles for content */
}
```

### Open and closed state

The hover card exposes a `data-state` attribute that can be used to style the
hover card based on its open-close state.

```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 */
}
```

### Arrow

Zag exposes some variable that can be used to style the arrow.

```css
[data-part="arrow"] {
  /* styles for arrow */
  --arrow-background: white;
  --arrow-size: 8px;
}
```

```css
[data-part="content"] {
  /* styles for content */
}
```

## Methods and Properties

### Machine Context

The hover card machine exposes the following context properties:

**`ids`**
Type: `Partial<{ trigger: string; content: string; positioner: string; arrow: string; }>`
Description: The ids of the elements in the popover. Useful for composition.

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Function called when the hover card opens or closes.

**`openDelay`**
Type: `number`
Description: The duration from when the mouse enters the trigger until the hover card opens.

**`closeDelay`**
Type: `number`
Description: The duration from when the mouse leaves the trigger or content until the hover card closes.

**`open`**
Type: `boolean`
Description: The controlled open state of the hover card

**`defaultOpen`**
Type: `boolean`
Description: The initial open state of the hover card when rendered.
Use when you don't need to control the open state of the hover card.

**`positioning`**
Type: `PositioningOptions`
Description: The user provided options used to position the popover content

**`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 hover card `api` exposes the following methods:

**`open`**
Type: `boolean`
Description: Whether the hover card is open

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open the hover card

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => void`
Description: Function to reposition the popover

### Data Attributes

**`Trigger`**

**`data-scope`**: hover-card
**`data-part`**: trigger
**`data-placement`**: The placement of the trigger
**`data-state`**: "open" | "closed"

**`Content`**

**`data-scope`**: hover-card
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-placement`**: The placement of the content

## Accessibility

### Keyboard Interactions

The hover card is intended for mouse users only so will not respond to keyboard
navigation.



# Menu

An accessible dropdown and context menu that is used to display a list of
actions or options that a user can choose.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/menu)
[Logic Visualizer](https://zag-visualizer.vercel.app/menu)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/menu)



**Features**

- Support for items, labels, groups of items.
- Focus is fully managed using `aria-activedescendant` pattern.
- Typeahead to allow focusing items by typing text.
- Keyboard navigation support including arrow keys, home/end, page up/down.

## Installation

To use the menu machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/menu @zag-js/react
# or
yarn add @zag-js/menu @zag-js/react
```


This command will install the framework agnostic menu logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the menu 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

First, import the menu package into your project

```jsx
import * as menu from "@zag-js/menu"
```

The menu package exports two key functions:

- `machine` — The state machine logic for the menu widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
menu machine in your project 🔥

```jsx
import * as menu from "@zag-js/menu"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

export function Menu() {
  const service = useMachine(menu.machine, { id: useId() })

  const api = menu.connect(service, normalizeProps)

  return (
    <div>
      <button {...api.getTriggerProps()}>
        Actions <span {...api.getIndicatorProps()}>â–¾</span>
      </button>
      <div {...api.getPositionerProps()}>
        <ul {...api.getContentProps()}>
          <li {...api.getItemProps({ value: "edit" })}>Edit</li>
          <li {...api.getItemProps({ value: "duplicate" })}>Duplicate</li>
          <li {...api.getItemProps({ value: "delete" })}>Delete</li>
          <li {...api.getItemProps({ value: "export" })}>Export...</li>
        </ul>
      </div>
    </div>
  )
}
```


## Listening for item selection

When a menu item is clicked, the `onSelect` callback is invoked.

```jsx {3-6}
const service = useMachine(menu.machine, {
  onSelect(details) {
    // details => { value: string }
    console.log("selected value is ", details.value)
  },
})
```

## Listening for open state changes

When a menu is opened or closed, the `onOpenChange` callback is invoked.

```jsx {3-6}
const service = useMachine(menu.machine, {
  onOpenChange(details) {
    // details => { open: boolean }
    console.log("open state is ", details.open)
  },
})
```

## Grouping menu items

When the number of menu items gets much, it might be useful to group related
menu items. To achieve this:

- Wrap the menu items within an element.
- Spread the `api.getGroupProps(...)` JSX properties unto the element, providing
  an `id`.
- Render a label for the menu group, providing the `id` of the group element.

```jsx
//...
<div {...api.getContentProps()}>
  {/* ... */}
  <hr {...api.getSeparatorProps()} />
  <p {...api.getLabelProps({ htmlFor: "account" })}>Accounts</p>
  <div {...api.getGroupProps({ id: "account" })}>
    <button {...api.getItemProps({ id: "account-1" })}>Account 1</button>
    <button {...api.getItemProps({ id: "account-2" })}>Account 2</button>
  </div>
</div>
//...
```

## Checkbox and Radio option items

To use checkbox or radio option items, you'll need to:

- Add a `value` property to the machine's context whose value is an object
  describing the state of the option items.
- Use the `api.getOptionItemProps(...)` function to get the props for the option
  item.

A common requirement for the option item that you pass the `name`, `value` and
`type` properties.

- `type` — The type of option item. Either `"checkbox"` or `"radio"`.
- `value` — The value of the option item.
- `checked` — The checked state of the option item.
- `onCheckedChange` — The callback to invoke when the checked state changes.

```jsx
import * as menu from "@zag-js/menu"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useState } from "react"

const data = {
  order: [
    { label: "Ascending", value: "asc" },
    { label: "Descending", value: "desc" },
    { label: "None", value: "none" },
  ],
  type: [
    { label: "Email", value: "email" },
    { label: "Phone", value: "phone" },
    { label: "Address", value: "address" },
  ],
}

export function Menu() {
  const [order, setOrder] = useState("")
  const [type, setType] = useState([])

  const service = useMachine(menu.machine, { id: "1" })

  const api = menu.connect(service, normalizeProps)

  const radios = menuOptionData.order.map((item) => ({
    type: "radio",
    name: "order",
    value: item.value,
    label: item.label,
    checked: order === item.value,
    onCheckedChange: (checked) => setOrder(checked ? item.value : ""),
  }))

  const checkboxes = menuOptionData.type.map((item) => ({
    type: "checkbox",
    name: "type",
    value: item.value,
    label: item.label,
    checked: type.includes(item.value),
    onCheckedChange: (checked) =>
      setType((prev) =>
        checked ? [...prev, item.value] : prev.filter((x) => x !== item.value),
      ),
  }))

  return (
    <>
      <button {...api.getTriggerProps()}>Trigger</button>
      <div {...api.getPositionerProps()}>
        <div {...api.getContentProps()}>
          {radios.map((item) => {
            return (
              <div key={item.value} {...api.getOptionItemProps(item)}>
                <span {...api.getItemIndicatorProps(item)}>✅</span>
                <span {...api.getItemTextProps(item)}>{item.label}</span>
              </div>
            )
          })}
          <hr {...api.getSeparatorProps()} />
          {checkboxes.map((item) => {
            return (
              <div key={item.value} {...api.getOptionItemProps(item)}>
                <span {...api.getItemIndicatorProps(item)}>✅</span>
                <span {...api.getItemTextProps(item)}>{item.label}</span>
              </div>
            )
          })}
        </div>
      </div>
    </>
  )
}
```


## Styling guide

Earlier, we mentioned that each menu part has a `data-part` attribute added to
them to select and style them in the DOM.

### Open and closed state

When the menu is open or closed, the content and trigger parts will have the
`data-state` attribute.

```css
[data-part="content"][data-state="open|closed"] {
  /* styles for open or closed state */
}

[data-part="trigger"][data-state="open|closed"] {
  /* styles for open or closed state */
}
```

### Highlighted item 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 */
}

[data-part="item"][data-type="radio|checkbox"][data-highlighted] {
  /* styles for highlighted state */
}
```

### Disabled item state

When an item or an option item is disabled, it is given a `data-disabled`
attribute.

```css
[data-part="item"][data-disabled] {
  /* styles for disabled state */
}

[data-part="item"][data-type="radio|checkbox"][data-disabled] {
  /* styles for disabled state */
}
```

### Using arrows

When using arrows within the menu, you can style it using css variables.

```css
[data-part="arrow"] {
  --arrow-size: 20px;
  --arrow-background: red;
}
```

### Checked option item state

When an option item is checked, it is given a `data-state` attribute.

```css
[data-part="item"][data-type="radio|checkbox"][data-state="checked"] {
  /* styles for checked state */
}
```

## Methods and Properties

### Machine Context

The menu machine exposes the following context properties:

**`ids`**
Type: `Partial<{ trigger: string; contextTrigger: string; content: string; groupLabel(id: string): string; group(id: string): string; positioner: string; arrow: string; }>`
Description: The ids of the elements in the menu. Useful for composition.

**`defaultHighlightedValue`**
Type: `string`
Description: The initial highlighted value of the menu item when rendered.
Use when you don't need to control the highlighted value of the menu item.

**`highlightedValue`**
Type: `string`
Description: The controlled highlighted value of the menu item.

**`onHighlightChange`**
Type: `(details: HighlightChangeDetails) => void`
Description: Function called when the highlighted menu item changes.

**`onSelect`**
Type: `(details: SelectionDetails) => void`
Description: Function called when a menu item is selected.

**`anchorPoint`**
Type: `Point`
Description: The positioning point for the menu. Can be set by the context menu trigger or the button trigger.

**`loopFocus`**
Type: `boolean`
Description: Whether to loop the keyboard navigation.

**`positioning`**
Type: `PositioningOptions`
Description: The options used to dynamically position the menu

**`closeOnSelect`**
Type: `boolean`
Description: Whether to close the menu when an option is selected

**`aria-label`**
Type: `string`
Description: The accessibility label for the menu

**`open`**
Type: `boolean`
Description: The controlled open state of the menu

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Function called when the menu opens or closes

**`defaultOpen`**
Type: `boolean`
Description: The initial open state of the menu when rendered.
Use when you don't need to control the open state of the menu.

**`typeahead`**
Type: `boolean`
Description: Whether the pressing printable characters should trigger typeahead navigation

**`composite`**
Type: `boolean`
Description: Whether the menu is a composed with other composite widgets like a combobox or tabs

**`navigate`**
Type: `(details: NavigateDetails) => void`
Description: Function to navigate to the selected item if it's an anchor element

**`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.

**`onEscapeKeyDown`**
Type: `(event: KeyboardEvent) => void`
Description: Function called when the escape key is pressed

**`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 menu `api` exposes the following methods:

**`open`**
Type: `boolean`
Description: Whether the menu is open

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open or close the menu

**`highlightedValue`**
Type: `string`
Description: The id of the currently highlighted menuitem

**`setHighlightedValue`**
Type: `(value: string) => void`
Description: Function to set the highlighted menuitem

**`setParent`**
Type: `(parent: MenuService) => void`
Description: Function to register a parent menu. This is used for submenus

**`setChild`**
Type: `(child: MenuService) => void`
Description: Function to register a child menu. This is used for submenus

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => void`
Description: Function to reposition the popover

**`getOptionItemState`**
Type: `(props: OptionItemProps) => OptionItemState`
Description: Returns the state of the option item

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state of the menu item

### Data Attributes

**`Trigger`**

**`data-scope`**: menu
**`data-part`**: trigger
**`data-placement`**: The placement of the trigger
**`data-state`**: "open" | "closed"

**`Indicator`**

**`data-scope`**: menu
**`data-part`**: indicator
**`data-state`**: "open" | "closed"

**`Content`**

**`data-scope`**: menu
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-placement`**: The placement of the content

**`Item`**

**`data-scope`**: menu
**`data-part`**: item
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted
**`data-valuetext`**: The human-readable value

**`OptionItem`**

**`data-scope`**: menu
**`data-part`**: option-item
**`data-type`**: The type of the item
**`data-value`**: The value of the item
**`data-state`**: "checked" | "unchecked"
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted
**`data-valuetext`**: The human-readable value

**`ItemIndicator`**

**`data-scope`**: menu
**`data-part`**: item-indicator
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted
**`data-state`**: "checked" | "unchecked"

**`ItemText`**

**`data-scope`**: menu
**`data-part`**: item-text
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted
**`data-state`**: "checked" | "unchecked"

## Accessibility

Uses
[aria-activedescendant](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/)
pattern to manage focus movement among menu items.

### Keyboard Interactions

**`Space`**
Description: Activates/Selects the highlighted item

**`Enter`**
Description: Activates/Selects the highlighted item

**`ArrowDown`**
Description: Highlights the next item in the menu

**`ArrowUp`**
Description: Highlights the previous item in the menu

**`ArrowRight + ArrowLeft`**
Description: <span>When focus is on trigger, opens or closes the submenu depending on reading direction.</span>

**`Esc`**
Description: Closes the menu and moves focus to the trigger



# Context Menu

An accessible dropdown and context menu that is used to display a list of
actions or options that a user can choose when a trigger element is
right-clicked or long pressed.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/menu)
[Logic Visualizer](https://zag-visualizer.vercel.app/menu)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/menu)



**Features**

- Support for items, labels, groups of items.
- Focus is fully managed using `aria-activedescendant` pattern.
- Typeahead to allow focusing items by typing text.
- Keyboard navigation support including arrow keys, home/end, page up/down.

## Installation

To use the menu machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/menu @zag-js/react
# or
yarn add @zag-js/menu @zag-js/react
```


This command will install the framework agnostic menu logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the menu 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

First, import the menu package into your project

```jsx
import * as menu from "@zag-js/menu"
```

The menu package exports two key functions:

- `machine` — The state machine logic for the menu widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
menu machine in your project 🔥

To show the menu when a trigger element is right-clicked, use the
`contextTriggerProps` provided by the menu's connect function.

Context menu's are also opened during a long-press of roughly `700ms` when the
pointer is pen or touch.

```jsx
import * as menu from "@zag-js/menu"
import { useMachine, normalizeProps } from "@zag-js/react"

export function ContextMenu() {
  const service = useMachine(menu.machine, { id: "1" })
  const api = menu.connect(service, normalizeProps)

  return (
    <div>
      <div {...api.getContextTriggerProps()}>
        <div>Open context menu</div>
      </div>
      <div {...api.getPositionerProps()}>
        <ul {...api.getContentProps()}>
          <li {...api.getItemProps({ value: "edit" })}>Edit</li>
          <li {...api.getItemProps({ value: "duplicate" })}>Duplicate</li>
          <li {...api.getItemProps({ value: "delete" })}>Delete</li>
          <li {...api.getItemProps({ value: "export" })}>Export...</li>
        </ul>
      </div>
    </div>
  )
}
```


## Styling guide

Earlier, we mentioned that each menu part has a `data-part` attribute added to
them to select and style them in the DOM.

### Focused item state

When an item is focused, via keyboard navigation or pointer, it is given a
`data-focus` attribute.

```css
[data-part="item"][data-focus] {
  /* styles for focused state */
}

[data-part="item"][data-type="radio|checkbox"][data-focus] {
  /* styles for focused state */
}
```

### Disabled item state

When an item or an option item is disabled, it is given a `data-disabled`
attribute.

```css
[data-part="item"][data-disabled] {
  /* styles for disabled state */
}

[data-part="item"][data-type="radio|checkbox"][data-disabled] {
  /* styles for disabled state */
}
```

### Using arrows

When using arrows within the menu, you can style it using css variables.

```css
[data-part="arrow"] {
  --arrow-size: 20px;
  --arrow-background: red;
}
```

### Checked option item state

When an option item is checked, it is given a `data-checked` attribute.

```css
[data-part="item"][data-type="radio|checkbox"][data-checked] {
  /* styles for checked state */
}
```

## Methods and Properties

### Machine Context

The menu machine exposes the following context properties:



### Machine API

The menu `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="menu" />

## Accessibility

Uses
[aria-activedescendant](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/)
pattern to manage focus movement among menu items.

### Keyboard Interactions

**`Space`**
Description: Activates/Selects the highlighted item

**`Enter`**
Description: Activates/Selects the highlighted item

**`ArrowDown`**
Description: Highlights the next item in the menu

**`ArrowUp`**
Description: Highlights the previous item in the menu

**`ArrowRight + ArrowLeft`**
Description: When focus is on trigger, opens or closes the submenu depending on reading direction.

**`Esc`**
Description: Closes the context menu



# Nested Menu

An accessible dropdown and context menu that is used to display a list of
actions or options that a user can choose.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/menu)
[Logic Visualizer](https://zag-visualizer.vercel.app/menu)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/menu)



**Features**

- Support for items, labels, groups of items.
- Focus is fully managed using `aria-activedescendant` pattern.
- Typeahead to allow focusing items by typing text.
- Keyboard navigation support including arrow keys, home/end, page up/down.

## Installation

To use the menu machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/menu @zag-js/react
# or
yarn add @zag-js/menu @zag-js/react
```


This command will install the framework agnostic menu logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the menu 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

First, import the menu package into your project

```jsx
import * as menu from "@zag-js/menu"
```

The menu package exports two key functions:

- `machine` — The state machine logic for the menu widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
menu machine in your project 🔥

- Destructure the machine's **service** returned from the `useMachine` hook.
- Use the exposed `setParent` and `setChild` functions provided by the menu's
  connect function to assign the parent and child menus respectively.
- Create trigger item's using the `api.getTriggerItemProps(...)` function.

When building nested menus, you'll need to use:

- `setParent(...)` — Function to register a parent menu's machine in the child
  menu's context.
- `setChild(...)` — Function to register a child menu's machine in the parent
  menu's context.

```tsx
import * as menu from "@zag-js/menu"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import { useEffect } from "react"

export function NestedMenu() {
  // Level 1 - File Menu
  const fileMenuService = useMachine(menu.machine, {
    id: "1",
    "aria-label": "File",
  })

  const fileMenu = menu.connect(fileMenuService, normalizeProps)

  // Level 2 - Share Menu
  const shareMenuService = useMachine(menu.machine, {
    id: "2",
    "aria-label": "Share",
  })

  const shareMenu = menu.connect(shareMenuService, normalizeProps)

  useEffect(() => {
    setTimeout(() => {
      fileMenu.setChild(shareMenuService)
      shareMenu.setParent(fileMenuService)
    })
  }, [])

  // Share menu trigger
  const shareMenuTriggerProps = fileMenu.getTriggerItemProps(shareMenu)

  return (
    <>
      <button {...fileMenu.getTriggerProps()}>Click me</button>

      <Portal>
        <div {...fileMenu.getPositionerProps()}>
          <ul {...fileMenu.getContentProps()}>
            <li {...fileMenu.getItemProps({ value: "new-tab" })}>New tab</li>
            <li {...fileMenu.getItemProps({ value: "new-win" })}>New window</li>
            <li {...shareMenuTriggerProps}>Share</li>
            <li {...fileMenu.getItemProps({ value: "print" })}>Print...</li>
            <li {...fileMenu.getItemProps({ value: "help" })}>Help</li>
          </ul>
        </div>
      </Portal>

      <Portal>
        <div {...shareMenu.getPositionerProps()}>
          <ul {...shareMenu.getContentProps()}>
            <li {...shareMenu.getItemProps({ value: "messages" })}>Messages</li>
            <li {...shareMenu.getItemProps({ value: "airdrop" })}>Airdrop</li>
            <li {...shareMenu.getItemProps({ value: "whatsapp" })}>WhatsApp</li>
          </ul>
        </div>
      </Portal>
    </>
  )
}
```


## Styling guide

Earlier, we mentioned that each menu part has a `data-part` attribute added to
them to select and style them in the DOM.

### Highlighted item 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 */
}

[data-part="item"][data-type="radio|checkbox"][data-highlighted] {
  /* styles for highlighted state */
}
```

### Disabled item state

When an item or an option item is disabled, it is given a `data-disabled`
attribute.

```css
[data-part="item"][data-disabled] {
  /* styles for disabled state */
}

[data-part="item"][data-type="radio|checkbox"][data-disabled] {
  /* styles for disabled state */
}
```

### Using arrows

When using arrows within the menu, you can style it using css variables.

```css
[data-part="arrow"] {
  --arrow-size: 20px;
  --arrow-background: red;
}
```

### Checked option item state

When an option item is checked, it is given a `data-state` attribute.

```css
[data-part="item"][data-type="radio|checkbox"][data-state="checked"] {
  /* styles for checked state */
}
```

## Methods and Properties

### Machine Context

The menu machine exposes the following context properties:



### Machine API

The menu `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="menu" />

## Accessibility

Uses
[aria-activedescendant](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions-active-descendant/)
pattern to manage focus movement among menu items.

### Keyboard Interactions

**`Space`**
Description: Opens/closes the nested menu.

**`Enter`**
Description: Opens/closes the nested menu.

**`ArrowDown`**
Description: Moves focus to the next item.

**`ArrowUp`**
Description: Moves focus to the previous item.

**`ArrowRight`**
Description: Opens the nested menu.

**`ArrowLeft`**
Description: Closes the nested menu.

**`Esc`**
Description: Closes the nested menu and moves focus to the parent menu item.



# Number Input

The number input provides controls for editing, incrementing or decrementing
numeric values using the keyboard or pointer.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/number-input)
[Logic Visualizer](https://zag-visualizer.vercel.app/number-input)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/number-input)



**Features**

- Based on the spinbutton pattern.
- Supports using the scroll wheel to increment and decrement the value.
- Handles floating point rounding errors when incrementing, decrementing, and
  snapping to step.
- Supports pressing and holding the spin buttons to continuously increment or
  decrement.
- Supports rounding value to specific number of fraction digits.
- Support for scrubbing interaction.

## Installation

To use the number input machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/number-input @zag-js/react
# or
yarn add @zag-js/number-input @zag-js/react
```


This command will install the framework agnostic number input logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the number input 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

First, import the number input package into your project

```jsx
import * as numberInput from "@zag-js/number-input"
```

The number input package exports two key functions:

- `machine` — The state machine logic for the number input widget as described
  in the WAI-ARIA spinner pattern.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that the every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
number input machine in your project 🔥

```jsx
import * as numberInput from "@zag-js/number-input"
import { useMachine, normalizeProps } from "@zag-js/react"

export function NumberInput() {
  const service = useMachine(numberInput.machine, { id: "1" })

  const api = numberInput.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Enter number:</label>
      <div>
        <button {...api.getDecrementTriggerProps()}>DEC</button>
        <input {...api.getInputProps()} />
        <button {...api.getIncrementTriggerProps()}>INC</button>
      </div>
    </div>
  )
}
```


## Setting the initial value

To set the initial value of the number input, you can set the `value` context
property.

> **Note:** The value must be a string

```jsx {2}
const service = useMachine(numberInput.machine, {
  defaultValue: "13",
})
```

## Setting a minimum and maximum value

Pass the `min` prop or `max` prop to set an upper and lower limit for the input.
By default, the input will restrict the value to stay within the specified
range.

```jsx {2,3}
const service = useMachine(numberInput.machine, {
  min: 10,
  max: 200,
})
```

> To allow the value overflow the specified min or max, set the
> `allowOverflow: true` in the context.

## Scrubbing the input value

The number input machine supports the scrubber interaction pattern. The use this
pattern, spread the `scrubberProps` from the `api` on to the scrubbing element.

It uses the Pointer lock API and tracks the pointer movement. It also renders a
virtual cursor which mimics the real cursor's pointer.

```jsx {13}
import * as numberInput from "@zag-js/number-input"
import { useMachine, normalizeProps } from "@zag-js/react"

export function NumberInput() {
  const service = useMachine(numberInput.machine, { id: "1" })

  const api = numberInput.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Enter number:</label>
      <div>
        <div {...api.getScrubberProps()} />
        <input {...api.getInputProps()} />
      </div>
    </div>
  )
}
```


## Using the mousewheel to change value

The number input machine exposes a way to increment/decrement the value using
the mouse wheel event. To activate this, pass the `allowMouseWheel` property to
the machine's context.

```jsx {2}
const service = useMachine(numberInput.machine, {
  allowMouseWheel: true,
})
```

## Clamp value when user blurs the input

In most cases, users can type custom values in the input field. If the typed
value is greater than the max, the value is reset to max when the user blur out
of the input.

To disable this behavior, pass `clampValueOnBlur` and set to `false`.

```jsx {2}
const service = useMachine(numberInput.machine, {
  clampValueOnBlur: false,
})
```

## Listening for value changes

When the value changes, the `onValueChange` callback is invoked.

```jsx {2-7}
const service = useMachine(numberInput.machine, {
  onValueChange(details) {
    // details => { value: string, valueAsNumber: number }
    console.log("value is:", details.value)
  },
})
```

## Usage within forms

To use the number input within forms, set the `name` property in the machine's
context.

```jsx {2}
const service = useMachine(numberInput.machine, {
  name: "quantity",
})
```

## Adjusting the precision of the value

To format the input value to be rounded to specific decimal points, set the
`formatOptions` and provide `Intl.NumberFormatOptions` such as
`maximumFractionDigits` or `minimumFractionDigits`

```jsx {2-5}
const service = useMachine(numberInput.machine, {
  formatOptions: {
    maximumFractionDigits: 4,
    minimumFractionDigits: 2,
  },
})
```

## Disabling long press spin

To disable the long press spin, set the `spinOnPress` to `false`.

```jsx {2}
const service = useMachine(numberInput.machine, {
  spinOnPress: false,
})
```

## Format and parse value

To apply custom formatting to the input's value, set the `formatOptions` and
provide `Intl.NumberFormatOptions` such as `style` and `currency`

```jsx {2-5}
const service = useMachine(numberInput.machine, {
  formatOptions: {
    style: "currency",
    currency: "USD",
  },
})
```

## Styling guide

Earlier, we mentioned that each number-input's part has a `data-part` attribute
added to them to select and style them in the DOM.

### Disabled state

When the number input is disabled, the root, label and input parts will have
`data-disabled` attribute added to them.

The increment and decrement spin buttons are disabled when the number input is
disabled and the min/max is reached.

```css
[data-part="root"][data-disabled] {
  /* disabled styles for the input */
}

[data-part="input"][data-disabled] {
  /* disabled styles for the input */
}

[data-part="label"][data-disabled] {
  /* disabled styles for the label */
}

[data-part="increment-trigger"][data-disabled] {
  /* disabled styles for the increment button */
}

[data-part="decrement-trigger"][data-disabled] {
  /* disabled styles for the decrement button */
}
```

### Invalid state

The number input is invalid, either by passing `invalid: true` or when the value
exceeds the max and `allowOverflow: true` is passed. When this happens, the
root, label and input parts will have `data-invalid` attribute added to them.

```css
[data-part="root"][data-invalid] {
  /* disabled styles for the input */
}

[data-part="input"][data-invalid] {
  /* invalid styles for the input */
}

[data-part="label"][data-invalid] {
  /* invalid styles for the label */
}
```

### Readonly state

When the number input is readonly, the input part will have `data-readonly`
added.

```css
[data-part="input"][data-readonly] {
  /* readonly styles for the input */
}
```

### Increment and decrement spin buttons

The spin buttons can be styled individually with their respective `data-part`
attribute.

```css
[data-part="increment-trigger"] {
  /* styles for the increment trigger element */
}

[data-part="decrement-trigger"] {
  /* styles for the decrement trigger element */
}
```

## Methods and Properties

### Machine Context

The number input machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; label: string; input: string; incrementTrigger: string; decrementTrigger: string; scrubber: string; }>`
Description: The ids of the elements in the number input. Useful for composition.

**`name`**
Type: `string`
Description: The name attribute of the number input. Useful for form submission.

**`form`**
Type: `string`
Description: The associate form of the input element.

**`disabled`**
Type: `boolean`
Description: Whether the number input is disabled.

**`readOnly`**
Type: `boolean`
Description: Whether the number input is readonly

**`invalid`**
Type: `boolean`
Description: Whether the number input value is invalid.

**`required`**
Type: `boolean`
Description: Whether the number input is required

**`pattern`**
Type: `string`
Description: The pattern used to check the <input> element's value against

**`value`**
Type: `string`
Description: The controlled value of the input

**`defaultValue`**
Type: `string`
Description: The initial value of the input when rendered.
Use when you don't need to control the value of the input.

**`min`**
Type: `number`
Description: The minimum value of the number input

**`max`**
Type: `number`
Description: The maximum value of the number input

**`step`**
Type: `number`
Description: The amount to increment or decrement the value by

**`allowMouseWheel`**
Type: `boolean`
Description: Whether to allow mouse wheel to change the value

**`allowOverflow`**
Type: `boolean`
Description: Whether to allow the value overflow the min/max range

**`clampValueOnBlur`**
Type: `boolean`
Description: Whether to clamp the value when the input loses focus (blur)

**`focusInputOnChange`**
Type: `boolean`
Description: Whether to focus input when the value changes

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`formatOptions`**
Type: `Intl.NumberFormatOptions`
Description: The options to pass to the `Intl.NumberFormat` constructor

**`inputMode`**
Type: `InputMode`
Description: Hints at the type of data that might be entered by the user. It also determines
the type of keyboard shown to the user on mobile devices

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function invoked when the value changes

**`onValueInvalid`**
Type: `(details: ValueInvalidDetails) => void`
Description: Function invoked when the value overflows or underflows the min/max range

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Description: Function invoked when the number input is focused

**`spinOnPress`**
Type: `boolean`
Description: Whether to spin the value when the increment/decrement button is pressed

**`locale`**
Type: `string`
Description: The current locale. Based on the BCP 47 definition.

**`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 number input `api` exposes the following methods:

**`focused`**
Type: `boolean`
Description: Whether the input is focused.

**`invalid`**
Type: `boolean`
Description: Whether the input is invalid.

**`empty`**
Type: `boolean`
Description: Whether the input value is empty.

**`value`**
Type: `string`
Description: The formatted value of the input.

**`valueAsNumber`**
Type: `number`
Description: The value of the input as a number.

**`setValue`**
Type: `(value: number) => void`
Description: Function to set the value of the input.

**`clearValue`**
Type: `() => void`
Description: Function to clear the value of the input.

**`increment`**
Type: `() => void`
Description: Function to increment the value of the input by the step.

**`decrement`**
Type: `() => void`
Description: Function to decrement the value of the input by the step.

**`setToMax`**
Type: `() => void`
Description: Function to set the value of the input to the max.

**`setToMin`**
Type: `() => void`
Description: Function to set the value of the input to the min.

**`focus`**
Type: `() => void`
Description: Function to focus the input.

### Data Attributes

**`Root`**

**`data-scope`**: number-input
**`data-part`**: root
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused
**`data-invalid`**: Present when invalid

**`Label`**

**`data-scope`**: number-input
**`data-part`**: label
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused
**`data-invalid`**: Present when invalid

**`Control`**

**`data-scope`**: number-input
**`data-part`**: control
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid

**`ValueText`**

**`data-scope`**: number-input
**`data-part`**: value-text
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`Input`**

**`data-scope`**: number-input
**`data-part`**: input
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled

**`DecrementTrigger`**

**`data-scope`**: number-input
**`data-part`**: decrement-trigger
**`data-disabled`**: Present when disabled

**`IncrementTrigger`**

**`data-scope`**: number-input
**`data-part`**: increment-trigger
**`data-disabled`**: Present when disabled

**`Scrubber`**

**`data-scope`**: number-input
**`data-part`**: scrubber
**`data-disabled`**: Present when disabled

## Accessibility

### Keyboard Interactions

**`ArrowUp`**
Description: Increments the value of the number input by a predefined step.

**`ArrowDown`**
Description: Decrements the value of the number input by a predefined step.

**`PageUp`**
Description: Increments the value of the number input by a larger predefined step.

**`PageDown`**
Description: Decrements the value of the number input by a larger predefined step.

**`Home`**
Description: Sets the value of the number input to its minimum allowed value.

**`End`**
Description: Sets the value of the number input to its maximum allowed value.

**`Enter`**
Description: Submits the value entered in the number input.



# Pagination

Pagination is an interface that allows navigating between pages that contain
split information, instead of being shown on a single page.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/pagination)
[Logic Visualizer](https://zag-visualizer.vercel.app/pagination)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/pagination)



**Features**

- Full keyboard navigation.
- Optimized for screen readers.

## Installation

To use the pagination machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/pagination @zag-js/react
# or
yarn add @zag-js/pagination @zag-js/react
```


This command will install the framework agnostic pagination logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the pagination 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

First, import the pagination package into your project

```jsx
import * as pagination from "@zag-js/pagination"
```

The pagination package exports two key functions:

- `machine` — The state machine logic for the pagination widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

```jsx
import * as pagination from "@zag-js/pagination"
import { useMachine, normalizeProps } from "@zag-js/react"
import { data } from "./data"

function Pagination() {
  const service = useMachine(pagination.machine, {
    id: "1",
    count: data.length,
  })

  const api = pagination.connect(service, normalizeProps)

  return (
    <div>
      {api.totalPages > 1 && (
        <nav {...api.getRootProps()}>
          <ul>
            <li>
              <a href="#previous" {...api.getPrevTriggerProps()}>
                Previous <span className="visually-hidden">Page</span>
              </a>
            </li>
            {api.pages.map((page, i) => {
              if (page.type === "page")
                return (
                  <li key={page.value}>
                    <a href={`#${page.value}`} {...api.getItemProps(page)}>
                      {page.value}
                    </a>
                  </li>
                )
              else
                return (
                  <li key={`ellipsis-${i}`}>
                    <span {...api.getEllipsisProps({ index: i })}>&#8230;</span>
                  </li>
                )
            })}
            <li>
              <a href="#next" {...api.getNextTriggerProps()}>
                Next <span className="visually-hidden">Page</span>
              </a>
            </li>
          </ul>
        </nav>
      )}
    </div>
  )
}
```


```jsx
const api = connect(service)

// You can slice the data, to get data for current page
const currentPageData = data.slice(api.pageRange.start, api.pageRange.end)

api.page
// => 1

api.setPage(3)
// page => 3

api.previousPage
// => 2

api.nextPage
// => 4

api.pages
/*
    [
      {
        "type": "page",
        "value": 1,
      },
      {
        "type": "page",
        "value": 2,
      },
      {
        "type": "ellipsis",
      },
      {
        "type": "page",
        "value": 3,
      },
      {
        "type": "page",
        "value": 4,
      },
    ]
*/

api.pageRange
// => { start: 4, end: 13 }
```

## Styling guide

Earlier, we mentioned that each pagination part has a `data-part` attribute
added to them to select and style them in the DOM.

```css
[data-part="root"] {
  /* styles for the pagination's root */
}

[data-part="item"] {
  /* styles for the pagination's items */
}

[data-part="ellipsis"] {
  /* styles for the pagination's ellipsis */
}

[data-part="prev-trigger"] {
  /* styles for the pagination's previous page trigger */
}

[data-part="next-trigger"] {
  /* styles for the pagination's next page trigger */
}

/* We add a data-disabled attribute to the prev/next items when on the first/last page  */

[data-part="prev-trigger"][data-disabled] {
  /* styles for the pagination's previous page trigger when on first page */
}

[data-part="next-trigger"][data-disabled] {
  /* styles for the pagination's next page trigger when on first page */
}
```

## Methods and Properties

### Machine Context

The pagination machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; ellipsis(index: number): string; prevTrigger: string; nextTrigger: string; item(page: number): string; }>`
Description: The ids of the elements in the accordion. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`count`**
Type: `number`
Description: Total number of data items

**`pageSize`**
Type: `number`
Description: The controlled number of data items per page

**`defaultPageSize`**
Type: `number`
Description: The initial number of data items per page when rendered.
Use when you don't need to control the page size of the pagination.

**`siblingCount`**
Type: `number`
Description: Number of pages to show beside active page

**`page`**
Type: `number`
Description: The controlled active page

**`defaultPage`**
Type: `number`
Description: The initial active page when rendered.
Use when you don't need to control the active page of the pagination.

**`onPageChange`**
Type: `(details: PageChangeDetails) => void`
Description: Called when the page number is changed

**`onPageSizeChange`**
Type: `(details: PageSizeChangeDetails) => void`
Description: Called when the page size is changed

**`type`**
Type: `"button" | "link"`
Description: The type of the trigger element

**`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 pagination `api` exposes the following methods:

**`page`**
Type: `number`
Description: The current page.

**`count`**
Type: `number`
Description: The total number of data items.

**`pageSize`**
Type: `number`
Description: The number of data items per page.

**`totalPages`**
Type: `number`
Description: The total number of pages.

**`pages`**
Type: `Pages`
Description: The page range. Represented as an array of page numbers (including ellipsis)

**`previousPage`**
Type: `number`
Description: The previous page.

**`nextPage`**
Type: `number`
Description: The next page.

**`pageRange`**
Type: `PageRange`
Description: The page range. Represented as an object with `start` and `end` properties.

**`slice`**
Type: `<V>(data: V[]) => V[]`
Description: Function to slice an array of data based on the current page.

**`setPageSize`**
Type: `(size: number) => void`
Description: Function to set the page size.

**`setPage`**
Type: `(page: number) => void`
Description: Function to set the current page.

**`goToNextPage`**
Type: `() => void`
Description: Function to go to the next page.

**`goToPrevPage`**
Type: `() => void`
Description: Function to go to the previous page.

**`goToFirstPage`**
Type: `() => void`
Description: Function to go to the first page.

**`goToLastPage`**
Type: `() => void`
Description: Function to go to the last page.

### Data Attributes

**`Item`**

**`data-scope`**: pagination
**`data-part`**: item
**`data-index`**: The index of the item
**`data-selected`**: Present when selected

**`PrevTrigger`**

**`data-scope`**: pagination
**`data-part`**: prev-trigger
**`data-disabled`**: Present when disabled

**`NextTrigger`**

**`data-scope`**: pagination
**`data-part`**: next-trigger
**`data-disabled`**: Present when disabled



# Pin Input

The pin input is optimized for entering a sequence of digits or letters. The
input fields allow one character at a time. When the digit or letter is entered,
focus transfers to the next input in the sequence, until every input is filled.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/pin-input)
[Logic Visualizer](https://zag-visualizer.vercel.app/pin-input)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/pin-input)



**Features**

- Automatically focuses the next field on typing and focuses the previous field
  on deletion.
- Supports numeric and alphanumeric values.
- Support for masking value (for sensitive data).
- Support for copy/paste to autofill all fields.
- Supports fast paste SMS-code.

## Installation

To use the pin input machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/pin-input @zag-js/react
# or
yarn add @zag-js/pin-input @zag-js/react
```


This command will install the framework agnostic pin input logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the pin input 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

First, import the pin input package into your project

```jsx
import * as pinInput from "@zag-js/pin-input"
```

The pin input package exports two key functions:

- `machine` — The state machine logic for the pin input widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that the every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the pin
input machine in your project 🔥

```jsx
import * as pinInput from "@zag-js/pin-input"
import { useMachine, normalizeProps } from "@zag-js/react"

export function PinInput() {
  const service = useMachine(pinInput.machine, { id: "1" })

  const api = pinInput.connect(service, normalizeProps)

  return (
    <div>
      <div {...api.getRootProps()}>
        <input {...api.getInputProps({ index: 0 })} />
        <input {...api.getInputProps({ index: 1 })} />
        <input {...api.getInputProps({ index: 2 })} />
      </div>
      <button onClick={api.clearValue}>Clear</button>
    </div>
  )
}
```


## Setting a default value

To set the initial value of the pin input, pass the `value` property to the
machine's context.

```jsx {2}
const service = useMachine(pinInput.machine, {
  defaultValue: ["1", "2", ""],
})
```

## Changing the placeholder

To customize the default pin input placeholder (â—‹) for each input, pass the
`placeholder` prop and set it to your desired value.

```jsx {2}
const service = useMachine(pinInput.machine, {
  placeholder: "*",
})
```

## Blur on complete

By default, the last input maintains focus when filled and we invoke the
`onComplete` callback. To blur the last input when the user completes the input,
set the `blurOnComplete: true` in the machine's context.

```jsx {2}
const service = useMachine(pinInput.machine, {
  blurOnComplete: true,
})
```

## Allowing alphanumeric values

By default, the pin input accepts only number values but you can choose between
`numeric`, `alphanumeric` and `alphabetic` values. To change the input mode,
pass the `type` context property and set its value to `alphanumeric`.

```jsx {2}
const service = useMachine(pinInput.machine, {
  type: "alphanumeric",
})
```

## Using OTP mode

To trigger smartphone OTP auto-suggestion, it is recommended to set the
`autocomplete` attribute to "one-time-code". The pin-input machine provides
support for this automatically when you set the `otp` context property to
`true`.

```jsx {2}
const service = useMachine(pinInput.machine, {
  otp: true,
})
```

## Securing the text input

When collecting private or sensitive information using the pin input, you might
need to mask the value entered, similar to `<input type="password"/>`. Pass the
`mask` context property and set it to `true`.

```jsx {2}
const service = useMachine(pinInput.machine, {
  mask: true,
})
```

## Listening for changes

The pin input machine invokes several callback functions when the user enters:

- `onValueChange` — Function invoked when the value is changed.
- `onValueComplete` — Function invoked when all fields have been completed (by
  typing or pasting).
- `onValueInvalid` — Function invoked when an invalid value is entered into the
  input. An invalid value is any value that doesn't match the specified "type".

```jsx
const service = useMachine(pinInput.machine, {
  onValueChange(value) {
    // value => string[]
    console.log("value changed to:", value)
  },
  onValueComplete(details) {
    // details => { value: string[], valueAsString: string }
    console.log("completed value:", details)
  },
  onValueInvalid(details) {
    // details => { index: number, value: string }
    console.log("invalid value:", details)
  },
})
```

## RTL support

The pin input machine supports RTL writing directions. To set the `dir` property
in the machine's context.

When this attribute is set, we attach a `dir` attribute to the root part.

```jsx {2}
const service = useMachine(pinInput.machine, {
  dir: "rtl",
})
```

## Styling guide

Earlier, we mentioned that each pin input's part has a `data-part` attribute
added to them to select and style them in the DOM.

### Completed state

When all values have been filled, we attach a `data-complete` attribute to the
root and input parts.

```css
[data-part="root"][data-complete] {
  /* styles for when all value has been filled */
}

[data-part="input"][data-complete] {
  /* styles for when all value has been filled */
}
```

### Invalid state

When an invalid value is entered, we attach a `data-invalid` attribute to the
affected input part.

```css
[data-part="input"][data-invalid] {
  /* styles for when the input is invalid */
}
```

### Disabled state

When the pin-input is disabled, we attach a `data-disabled` attribute to the
root and input parts.

```css
[data-part="root"][data-disabled] {
  /* styles for when the input is disabled */
}

[data-part="input"][data-invalid] {
  /* styles for when the input is disabled */
}
```

## Methods and Properties

### Machine Context

The pin input machine exposes the following context properties:

**`name`**
Type: `string`
Description: The name of the input element. Useful for form submission.

**`form`**
Type: `string`
Description: The associate form of the underlying input element.

**`pattern`**
Type: `string`
Description: The regular expression that the user-entered input value is checked against.

**`ids`**
Type: `Partial<{ root: string; hiddenInput: string; label: string; control: string; input(id: string): string; }>`
Description: The ids of the elements in the pin input. Useful for composition.

**`disabled`**
Type: `boolean`
Description: Whether the inputs are disabled

**`placeholder`**
Type: `string`
Description: The placeholder text for the input

**`autoFocus`**
Type: `boolean`
Description: Whether to auto-focus the first input.

**`invalid`**
Type: `boolean`
Description: Whether the pin input is in the invalid state

**`required`**
Type: `boolean`
Description: Whether the pin input is required

**`readOnly`**
Type: `boolean`
Description: Whether the pin input is in the valid state

**`otp`**
Type: `boolean`
Description: If `true`, the pin input component signals to its fields that they should
use `autocomplete="one-time-code"`.

**`value`**
Type: `string[]`
Description: The controlled value of the the pin input.

**`defaultValue`**
Type: `string[]`
Description: The initial value of the the pin input when rendered.
Use when you don't need to control the value of the pin input.

**`type`**
Type: `"alphanumeric" | "numeric" | "alphabetic"`
Description: The type of value the pin-input should allow

**`onValueComplete`**
Type: `(details: ValueChangeDetails) => void`
Description: Function called when all inputs have valid values

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function called on input change

**`onValueInvalid`**
Type: `(details: ValueInvalidDetails) => void`
Description: Function called when an invalid value is entered

**`mask`**
Type: `boolean`
Description: If `true`, the input's value will be masked just like `type=password`

**`blurOnComplete`**
Type: `boolean`
Description: Whether to blur the input when the value is complete

**`selectOnFocus`**
Type: `boolean`
Description: Whether to select input value when input is focused

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`count`**
Type: `number`
Description: The number of inputs to render to improve SSR aria attributes.
This will be required in next major version.

**`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 pin input `api` exposes the following methods:

**`value`**
Type: `string[]`
Description: The value of the input as an array of strings.

**`valueAsString`**
Type: `string`
Description: The value of the input as a string.

**`complete`**
Type: `boolean`
Description: Whether all inputs are filled.

**`count`**
Type: `number`
Description: The number of inputs to render

**`items`**
Type: `number[]`
Description: The array of input values.

**`setValue`**
Type: `(value: string[]) => void`
Description: Function to set the value of the inputs.

**`clearValue`**
Type: `() => void`
Description: Function to clear the value of the inputs.

**`setValueAtIndex`**
Type: `(index: number, value: string) => void`
Description: Function to set the value of the input at a specific index.

**`focus`**
Type: `() => void`
Description: Function to focus the pin-input. This will focus the first input.

### Data Attributes

**`Root`**

**`data-scope`**: pin-input
**`data-part`**: root
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-complete`**: Present when the pin-input value is complete
**`data-readonly`**: Present when read-only

**`Label`**

**`data-scope`**: pin-input
**`data-part`**: label
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-complete`**: Present when the label value is complete
**`data-readonly`**: Present when read-only

**`Input`**

**`data-scope`**: pin-input
**`data-part`**: input
**`data-disabled`**: Present when disabled
**`data-complete`**: Present when the input value is complete
**`data-index`**: The index of the item
**`data-invalid`**: Present when invalid

## Accessibility

### Keyboard Interactions

**`ArrowLeft`**
Description: Moves focus to the previous input

**`ArrowRight`**
Description: Moves focus to the next input

**`Backspace`**
Description: Deletes the value in the current input and moves focus to the previous input

**`Delete`**
Description: Deletes the value in the current input

**`Control + V`**
Description: Pastes the value into the input fields



# Popover

A popover is a non-modal dialog that floats around a trigger. It is used to
display contextual information to the user, and should be paired with a
clickable trigger element.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/popover)
[Logic Visualizer](https://zag-visualizer.vercel.app/popover)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/popover)



**Features**

- Focus is managed and can be customized.
- Supports modal and non-modal modes.
- Ensures correct DOM order after tabbing out of the popover, whether it's
  portalled or not.

## Installation

To use the popover machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/popover @zag-js/react
# or
yarn add @zag-js/popover @zag-js/react
```


This command will install the framework agnostic popover logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the popover 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

First, import the popover package into your project

```jsx
import * as popover from "@zag-js/popover"
```

The popover package exports two key functions:

- `machine` — The state machine logic for the popover widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
popover machine in your project 🔥

```jsx
import { useId } from "react"
import * as popover from "@zag-js/popover"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"

export function Popover() {
  const service = useMachine(popover.machine, { id: useId() })

  const api = popover.connect(service, normalizeProps)

  const Wrapper = api.portalled ? Portal : React.Fragment

  return (
    <div>
      <button {...api.getTriggerProps()}>Click me</button>
      <Wrapper>
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>
            <div {...api.getTitleProps()}>Presenters</div>
            <div {...api.getDescriptionProps()}>Description</div>
            <button>Action Button</button>
            <button {...api.getCloseTriggerProps()}>X</button>
          </div>
        </div>
      </Wrapper>
    </div>
  )
}
```


## Rendering the popover in a portal

By default, the popover is rendered in the same DOM hierarchy as the trigger. To
render the popover within a portal, pass `portalled: true` property to the
machine's context.

> Note: This requires that you render the component within a `Portal` based on
> the framework you use.

```jsx
import * as popover from "@zag-js/popover"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import * as React from "react"

export function Popover() {
  const service = useMachine(popover.machine, { id: "1" })

  const api = popover.connect(service, normalizeProps)

  return (
    <div>
      <button {...api.getTriggerProps()}>Click me</button>
      <Portal>
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>
            <div {...api.getTitleProps()}>Presenters</div>
            <div {...api.getDescriptionProps()}>Description</div>
            <button>Action Button</button>
            <button {...api.getCloseTriggerProps()}>X</button>
          </div>
        </div>
      </Portal>
    </div>
  )
}
```


## Managing focus within popover

When the popover open, focus is automatically set to the first focusable element
within the popover. To customize the element that should get focus, set the
`initialFocusEl` property in the machine's context.

```jsx {3,7,15}
export function Popover() {
  // initial focused element ref
  const inputRef = useRef(null)

  const service = useMachine(popover.machine, {
    id: "1",
    initialFocusEl: () => inputRef.current,
  })

  // ...

  return (
    //...
    <input ref={inputRef} />
    // ...
  )
}
```


## Changing the modality

In some cases, you might want the popover to be **modal**. This means that
it'll:

- trap focus within its content
- block scrolling on the `body`
- disable pointer interactions outside the popover
- hide content behind the popover from screen readers

To make the popover modal, set the `modal: true` property in the machine's
context. When `modal: true`, we set the `portalled` attribute to `true` as well.

> **Note**: This requires that you render the component within a `Portal`.

```jsx {2}
const service = useMachine(popover.machine, {
  modal: true,
})
```

## Close behavior

The popover is designed to close on blur and when the `esc` key is pressed.

To prevent it from closing on blur (clicking or focusing outside), pass the
`closeOnInteractOutside` property and set it to `false`.

```jsx {2}
const service = useMachine(popover.machine, {
  closeOnInteractOutside: true,
})
```

To prevent it from closing when the `esc` key is pressed, pass the
`closeOnEscape` property and set it to `false`.

```jsx {2}
const service = useMachine(popover.machine, {
  closeOnEscape: true,
})
```

## Adding an arrow

To render an arrow within the popover, use the `api.getArrowProps()` and
`api.getArrowTipProps()`.

```jsx {6-8}
//...
const api = popover.connect(service, normalizeProps)
//...
return (
  <div {...api.getPositionerProps()}>
    <div {...api.getArrowProps()}>
      <div {...api.getArrowTipProps()} />
    </div>
    <div {...api.getContentProps()}>{/* ... */}</div>
  </div>
)
//...
```

## Changing the placement

To change the placement of the popover, set the `positioning.placement` property
in the machine's context.

```jsx {2-4}
const service = useMachine(popover.machine, {
  positioning: {
    placement: "top-start",
  },
})
```

## Listening for open state changes

When the popover is opened or closed, the `onOpenChange` callback is invoked.

```jsx {2-7}
const service = useMachine(popover.machine, {
  onOpenChange(details) {
    // details => { open: boolean }
    console.log("Popover", details.open)
  },
})
```

## Usage within dialog

When using the popover within a dialog, avoid rendering the popover in a
`Portal` or `Teleport`. This is because the dialog will trap focus within it,
and the popover will be rendered outside the dialog.

## Styling guide

Earlier, we mentioned that each popover part has a `data-part` attribute added
to them to select and style them in the DOM.

### Open and closed state

When the popover is expanded, we add a `data-state` and `data-placement`
attribute to the trigger.

```css
[data-part="trigger"][data-state="open|closed"] {
  /* styles for the expanded state */
}

[data-part="content"][data-state="open|closed"] {
  /* styles for the expanded state */
}

[data-part="trigger"][data-placement="(top|bottom)-(start|end)"] {
  /* styles for computed placement */
}
```

### Position aware

When the popover is expanded, we add a `data-state` and `data-placement`
attribute to the trigger.

```css
[data-part="trigger"][data-placement="(top|bottom)-(start|end)"] {
  /* styles for computed placement */
}

[data-part="content"][data-placement="(top|bottom)-(start|end)"] {
  /* styles for computed placement */
}
```

### Arrow

The arrow element requires specific css variables to be set for it to show
correctly.

```css
[data-part="arrow"] {
  --arrow-background: white;
  --arrow-size: 16px;
}
```

A common technique for adding a shadow to the arrow is to use set
`filter: drop-down(...)` css property on the content element. Alternatively, you
can use the `--arrow-shadow-color` variable.

```css
[data-part="arrow"] {
  --arrow-shadow-color: gray;
}
```

## Methods and Properties

### Machine Context

The popover machine exposes the following context properties:

**`ids`**
Type: `Partial<{ anchor: string; trigger: string; content: string; title: string; description: string; closeTrigger: string; positioner: string; arrow: string; }>`
Description: The ids of the elements in the popover. Useful for composition.

**`modal`**
Type: `boolean`
Description: Whether the popover should be modal. When set to `true`:
- interaction with outside elements will be disabled
- only popover content will be visible to screen readers
- scrolling is blocked
- focus is trapped within the popover

**`portalled`**
Type: `boolean`
Description: Whether the popover is portalled. This will proxy the tabbing behavior regardless of the DOM position
of the popover content.

**`autoFocus`**
Type: `boolean`
Description: Whether to automatically set focus on the first focusable
content within the popover when opened.

**`initialFocusEl`**
Type: `() => HTMLElement`
Description: The element to focus on when the popover is opened.

**`closeOnInteractOutside`**
Type: `boolean`
Description: Whether to close the popover when the user clicks outside of the popover.

**`closeOnEscape`**
Type: `boolean`
Description: Whether to close the popover when the escape key is pressed.

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Function invoked when the popover opens or closes

**`positioning`**
Type: `PositioningOptions`
Description: The user provided options used to position the popover content

**`open`**
Type: `boolean`
Description: The controlled open state of the popover

**`defaultOpen`**
Type: `boolean`
Description: The initial open state of the popover when rendered.
Use when you don't need to control the open state of the popover.

**`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.

**`onEscapeKeyDown`**
Type: `(event: KeyboardEvent) => void`
Description: Function called when the escape key is pressed

**`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 popover `api` exposes the following methods:

**`portalled`**
Type: `boolean`
Description: Whether the popover is portalled.

**`open`**
Type: `boolean`
Description: Whether the popover is open

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open or close the popover

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => void`
Description: Function to reposition the popover

### Data Attributes

**`Trigger`**

**`data-scope`**: popover
**`data-part`**: trigger
**`data-placement`**: The placement of the trigger
**`data-state`**: "open" | "closed"

**`Indicator`**

**`data-scope`**: popover
**`data-part`**: indicator
**`data-state`**: "open" | "closed"

**`Content`**

**`data-scope`**: popover
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-expanded`**: Present when expanded
**`data-placement`**: The placement of the content

## Accessibility

Adheres to the
[Dialog WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal).

### Keyboard Interactions

**`Space`**
Description: Opens/closes the popover.

**`Enter`**
Description: Opens/closes the popover.

**`Tab`**
Description: <span>Moves focus to the next focusable element within the content.<br /><strong>Note:</strong> If there are no focusable elements, focus is moved to the next focusable element after the trigger.</span>

**`Shift + Tab`**
Description: <span>Moves focus to the previous focusable element within the content<br /><strong>Note:</strong> If there are no focusable elements, focus is moved to the trigger.</span>

**`Esc`**
Description: <span>Closes the popover and moves focus to the trigger.</span>



# Presence

The presence machine is a state machine that helps you manage exit animations in
your project.

In the DOM, when a component is removed from the tree or hidden, it's removed
instantly. The presence machine suspends the component to allow its exit
animation before removing or hiding it.

> The presence machine requires using **CSS animations** to animate the
> component's exit.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/presence)
[Logic Visualizer](https://zag-visualizer.vercel.app/presence)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/presence)



## Installation

To use the presence machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/presence @zag-js/react
# or
yarn add @zag-js/presence @zag-js/react
```


This command will install the framework agnostic presence logic and the reactive
utilities for your framework of choice.

## Usage

First, import the presence package into your project

```jsx
import * as presence from "@zag-js/presence"
```

The presence package exports two key functions:

- `machine` — The state machine logic for the presence.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
presence machine in your project 🔥

```tsx
import * as presence from "@zag-js/presence"
import { useMachine, normalizeProps } from "@zag-js/react"

interface PresenceProps {
  present: boolean
  unmountOnExit?: boolean
  onExitComplete?: () => void
}

function Presence(props: PresenceProps) {
  const { unmountOnExit, present, onExitComplete, ...rest } = props

  const service = useMachine(presence.machine, {
    present,
    onExitComplete,
  })

  const api = presence.connect(service, normalizeProps)

  if (!api.present && unmountOnExit) return null

  return (
    <div
      hidden={!api.present}
      data-state={api.skip ? undefined : present ? "open" : "closed"}
      ref={api.setNode}
      {...rest}
    />
  )
}
```


## Styling guide

To style any entry and exit animations, set up the `@keyframes` and apply the
animations.

```css
@keyframes enter {
  from {
    scale: 0.9;
    opacity: 0;
  }

  to {
    opacity: 1;
    scale: 1;
  }
}

@keyframes exit {
  to {
    opacity: 0;
    scale: 0.9;
  }
}

[data-state="open"] {
  animation: enter 0.15s ease-out;
}

[data-state="closed"] {
  animation: exit 0.1s ease-in;
}
```

You can then use the `Presence` component in your project.

```jsx
function Example() {
  const [open, setOpen] = React.useState(true)
  return (
    <>
      <button onClick={() => setOpen((c) => !c)}>Toggle</button>
      <Presence present={open} unmountOnExit>
        <div>Content</div>
      </Presence>
    </>
  )
}
```

## Methods and Properties

### Machine Context

The presence machine exposes the following context properties:

**`present`**
Type: `boolean`
Description: Whether the node is present (controlled by the user)

**`onExitComplete`**
Type: `VoidFunction`
Description: Function called when the animation ends in the closed state

**`immediate`**
Type: `boolean`
Description: Whether to synchronize the present change immediately or defer it to the next frame

### Machine API

The presence `api` exposes the following methods:

**`skip`**
Type: `boolean`
Description: Whether the animation should be skipped.

**`present`**
Type: `boolean`
Description: Whether the node is present in the DOM.

**`setNode`**
Type: `(node: HTMLElement) => void`
Description: Function to set the node (as early as possible)

**`unmount`**
Type: `() => void`
Description: Function to programmatically unmount the node



# Linear Progress

Linear progress is a simple progress bar that can be used to show the progress
of a task such as downloading a file, uploading an image, etc.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/progress)
[Logic Visualizer](https://zag-visualizer.vercel.app/progress)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/progress)



**Features**

- Support for minimum and maximum values.
- Support for indeterminate progress bars.

## Installation

To use the progress machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/progress @zag-js/react
# or
yarn add @zag-js/progress @zag-js/react
```


This command will install the framework agnostic progress logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the progress 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

First, import the progress package into your project

```jsx
import * as progress from "@zag-js/progress"
```

The progress package exports two key functions:

- `machine` — The state machine logic for the progress widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
progress machine in your project 🔥

```jsx
import * as progress from "@zag-js/progress"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId } from "react"

function Progress() {
  const service = useMachine(progress.machine, { id: useId() })

  const api = progress.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getLabelProps()}>Upload progress</div>
      <div {...api.getTrackProps()}>
        <div {...api.getRangeProps()} />
      </div>
    </div>
  )
}
```


## Setting the value

Use the `api.setValue` method to set the value of the progress bar.

```jsx {2}
const service = useMachine(progress.machine, {
  value: 50,
})
```

## Setting the minimum and maximum values

By default, the progress bar has a minimum value of `0` and a maximum value of
`100`. You can change these values by passing the `min` and `max` options to the
machine.

```jsx {2-3}
const service = useMachine(progress.machine, {
  min: 0,
  max: 1000,
})
```

## Using the indeterminate state

The progress component is determinate by default, with the value and max set to
`50` and `100` respectively.

Set `value` to `null` to indicate an indeterminate value for operations whose
progress can't be determined (e.g., attempting to reconnect to a server).

```jsx {2}
const service = useMachine(progress.machine, {
  value: null,
})
```

## Showing a value text

Progress bars can only be interpreted by sighted users. To include a text
description to support assistive technologies like screen readers, use the
`valueText` part.

```jsx
const service = useMachine(progress.machine, {
  translations: {
    valueText: ({ value, max }) =>
      value == null ? "Loading..." : `${value} of ${max} items loaded`,
  },
})
```

Then you need to render the `valueText` part in your component.

```jsx
<div {...api.getValueTextProps()}>{api.valueAsString}</div>
```

## Styling guide

Earlier, we mentioned that each menu part has a `data-part` attribute added to
them to select and style them in the DOM.

```css
[data-scope="progress"][data-part="root"] {
  /* Styles for the root part */
}

[data-scope="progress"][data-part="track"] {
  /* Styles for the track part */
}

[data-scope="progress"][data-part="range"] {
  /* Styles for the range part */
}
```

### Indeterminate state

To style the indeterminate state, you can use the `[data-state=indeterminate]`
selector.

```css
[data-scope="progress"][data-part="root"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}

[data-scope="progress"][data-part="track"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}

[data-scope="progress"][data-part="range"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}
```

## Methods and Properties

### Machine Context

The progress machine exposes the following context properties:



### Machine API

The progress `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="progress" />



# Circular Progress

Circular progress is a circular progress bar that can be used to show the
progress of a task such as downloading a file, uploading an image, etc.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/progress)
[Logic Visualizer](https://zag-visualizer.vercel.app/progress)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/progress)



**Features**

- Support for minimum and maximum values.
- Support for indeterminate progress bars.

## Installation

To use the progress machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/progress @zag-js/react
# or
yarn add @zag-js/progress @zag-js/react
```


This command will install the framework agnostic progress logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the progress 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

First, import the progress package into your project

```jsx
import * as progress from "@zag-js/progress"
```

The progress package exports two key functions:

- `machine` — The state machine logic for the progress widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
progress machine in your project 🔥

```jsx
import * as progress from "@zag-js/progress"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId } from "react"

function Progress() {
  const service = useMachine(progress.machine, { id: useId() })

  const api = progress.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getLabelProps()}>Upload progress</div>
      <svg {...api.getCircleProps()}>
        <circle {...api.getCircleTrackProps()} />
        <circle {...api.getCircleRangeProps()} />
      </svg>
    </div>
  )
}
```


## Setting the value

Use the `api.setValue` method to set the value of the progress bar.

```jsx {2}
const service = useMachine(progress.machine, {
  defaultValue: 50,
})
```

## Setting the minimum and maximum values

By default, the progress bar has a minimum value of `0` and a maximum value of
`100`. You can change these values by passing the `min` and `max` options to the
machine.

```jsx {2-3}
const service = useMachine(progress.machine, {
  min: 0,
  max: 1000,
})
```

## Using the indeterminate state

The progress component is determinate by default, with the value and max set to
`50` and `100` respectively.

Set `value` to `null` to indicate an indeterminate value for operations whose
progress can't be determined (e.g., attempting to reconnect to a server).

```jsx {2}
const service = useMachine(progress.machine, {
  defaultValue: null,
})
```

## Showing a value text

Progress bars can only be interpreted by sighted users. To include a text
description to support assistive technologies like screen readers, use the
`valueText` part.

```jsx
const service = useMachine(progress.machine, {
  translations: {
    valueText: ({ value, max }) =>
      value == null ? "Loading..." : `${value} of ${max} items loaded`,
  },
})
```

## Setting the size of the progress bar

Use the `--size` CSS variable to set the size of the progress bar.

```css
[data-scope="progress"][data-part="circle"] {
  --size: 400px;
}
```

## Setting the thickness of the progress bar

Use the `--thickness` CSS variable to set the size of the progress bar.

```css
[data-scope="progress"][data-part="circle"] {
  --thickness: 4px;
}
```

Then you need to render the `valueText` part in your component.

```jsx
<div {...api.getValueTextProps()}>{api.valueAsString}</div>
```

## Styling guide

Earlier, we mentioned that each menu part has a `data-part` attribute added to
them to select and style them in the DOM.

```css
[data-scope="progress"][data-part="root"] {
  /* Styles for the root part */
}

[data-scope="progress"][data-part="circle-track"] {
  /* Styles for the track part */
}

[data-scope="progress"][data-part="circle-range"] {
  /* Styles for the range part */
}
```

### Indeterminate state

To style the indeterminate state, you can use the `[data-state=indeterminate]`
selector.

```css
[data-scope="progress"][data-part="root"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}

[data-scope="progress"][data-part="circle-track"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}

[data-scope="progress"][data-part="circle-range"][data-state="indeterminate"] {
  /* Styles for the root indeterminate state */
}
```

## Methods and Properties

### Machine Context

The progress machine exposes the following context properties:



### Machine API

The progress `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="progress" />



# QR Code

QR (Quick Response) Code is used to provide information or link which can be
accessed by scanning the code with an app or a smartphone.

> **Good to know**: The QR code encoding logic is built on top of the
> [`uqr`](https://github.com/unjs/uqr) library.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/qr-code)
[Logic Visualizer](https://zag-visualizer.vercel.app/qr-code)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/qr-code)



**Features**

- Renders an SVG element (good for SSR)
- Customize the size of the QR code in pixels
- Set the error correction level
- Customize the background and foreground color

## Installation

To use the QR code machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/qr-code @zag-js/react
# or
yarn add @zag-js/qr-code @zag-js/react
```


This command will install the framework agnostic QR code logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the QR code 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

First, import the QR code package into your project

```jsx
import * as qrCode from "@zag-js/qr-code"
```

The QR code package exports two key functions:

- `machine` — The state machine logic for the QR code widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the QR
code machine in your project 🔥

```jsx
import * as qrCode from "@zag-js/qr-code"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

export function QRCode() {
  const service = useMachine(qrCode.machine, {
    id: useId(),
    value: "https://github.com/chakra-ui",
  })

  const api = qrCode.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <svg {...api.getFrameProps()}>
        <path {...api.getPatternProps()} />
      </svg>
      <div {...api.getOverlayProps()}>
        <img
          src="https://avatars.githubusercontent.com/u/54212428?s=88&v=4"
          alt=""
        />
      </div>
    </div>
  )
}
```


## Setting the QR Code value

To set the value of the QR code, pass the `value` property to the machine.

```jsx {3}
const service = useMachine(qrCode.machine, {
  // ...
  value: "https://example.com",
})
```

## Setting the correction level

Error correction allows for the QR code to be blocked or resized while still
recognizable. In some cases where the link is too long or the logo overlay
covers a significant area, the error correction level can be increased.

The QR code machine accepts the following error correction levels:

- `L`: Allows recovery of up to 7% data loss (default)
- `M`: Allows recovery of up to 15% data loss
- `Q`: Allows recovery of up to 25% data loss
- `H`: Allows recovery of up to 30% data loss

To set the error correction level, pass the `encoding.ecc` or
`encoding.boostEcc` context property.

```jsx {3}
const service = useMachine(qrCode.machine, {
  value: "...",
  encoding: { ecc: "H" },
})
```

> The alternative is to enlarge the QRCode by increasing the size of the `svg`
> element.

## Adding an overlay logo

To add a logo overlay to the QR code, render the image part. The logo will be
automatically centered within the QR code.

```jsx {3}
<div {...api.getRootProps()}>
  <svg {...api.getFrameProps()}>{/** ... */}</svg>
  <div {...api.getOverlayProps()}>
    <img src="..." alt="" />
  </div>
</div>
```

## Changing the color

To change the color of the QR code, set the `fill` attribute on the `path` part.

```css
[data-scope="qr-code"][data-part="pattern"] {
  fill: green;
}
```

To change the background color of the QR code, set the `background-color`

```css
[data-scope="qr-code"][data-part="frame"] {
  background-color: white;
}
```

## Exporting the QR code

To export the QR code as an image, you can use the `api.getDataURL` method.

```ts
api.getDataURL({ type: "image/png" }).then((url) => {
  // do something with the URL (like download it)
})
```

## Styling guide

Earlier, we mentioned that each QR code part has a `data-part` attribute added
to them to select and style them in the DOM.

```css
[data-scope="qr-code"][data-part="root"] {
  /* Styles for the root part */
}

[data-scope="qr-code"][data-part="frame"] {
  /* Styles for the svg part */
}

[data-scope="qr-code"][data-part="pattern"] {
  /* Styles for the path */
}

[data-scope="qr-code"][data-part="overlay"] {
  /* Styles for the logo */
}
```

## Methods and Properties

### Machine Context

The QR code machine exposes the following context properties:

**`value`**
Type: `string`
Description: The controlled value to encode.

**`defaultValue`**
Type: `string`
Description: The initial value to encode when rendered.
Use when you don't need to control the value of the qr code.

**`ids`**
Type: `Partial<{ root: string; frame: string; }>`
Description: The element ids.

**`encoding`**
Type: `QrCodeGenerateOptions`
Description: The qr code encoding options.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Callback fired when the value changes.

**`pixelSize`**
Type: `number`
Description: The pixel size of the qr code.

**`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 QR code `api` exposes the following methods:

**`value`**
Type: `string`
Description: The value to encode.

**`setValue`**
Type: `(value: string) => void`
Description: Set the value to encode.

**`getDataUrl`**
Type: `(type: DataUrlType, quality?: number) => Promise<string>`
Description: Returns the data URL of the qr code.



# Radio Group

A radio group allows users to make a single choice from a select number of
option

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/radio-group)
[Logic Visualizer](https://zag-visualizer.vercel.app/radio-group)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/radio-group)



**Features**

- Syncs with `disabled` state of fieldset
- Syncs with form `reset` events
- Can programmatically set radio group value
- Can programmatically focus and blur radio items

## Installation

To use the radio machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/radio-group @zag-js/react
# or
yarn add @zag-js/radio-group @zag-js/react
```


This command will install the framework agnostic radio group logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the radio group 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

First, import the radio group package into your project

```jsx
import * as radio from "@zag-js/radio-group"
```

The radio package exports two key functions:

- `machine` — The state machine logic for the radio widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
radio machine in your project 🔥

```jsx
import * as radio from "@zag-js/radio-group"
import { useMachine, normalizeProps } from "@zag-js/react"

const items = [
  { id: "apple", label: "Apples" },
  { id: "orange", label: "Oranges" },
  { id: "mango", label: "Mangoes" },
  { id: "grape", label: "Grapes" },
]

function Radio() {
  const service = useMachine(radio.machine, { id: "1" })

  const api = radio.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <h3 {...api.getLabelProps()}>Fruits</h3>
      {items.map((opt) => (
        <label key={opt.id} {...api.getItemProps({ value: opt.id })}>
          <span {...api.getItemTextProps({ value: opt.id })}>{opt.label}</span>
          <input {...api.getItemHiddenInputProps({ value: opt.id })} />
          <div {...api.getItemControlProps({ value: opt.id })} />
        </label>
      ))}
    </div>
  )
}
```


## Disabling the radio group

To make a radio group disabled, set the context's `disabled` property to true

```jsx {2}
const service = useMachine(radio.machine, {
  disabled: true,
})
```

## Setting the initial value

To set the radio group's initial value, set the context's `value` property to
the value of the radio item to be selected by default

```jsx {2}
const service = useMachine(radio.machine, {
  defaultValue: "apple",
})
```

## Listening for changes

When the radio group value changes, the `onValueChange` callback is invoked.

```jsx {2-7}
const service = useMachine(radio.machine, {
  onValueChange(details) {
    // details => { value: string }
    console.log("radio value is:", details.value)
  },
})
```

## Usage within forms

To use radio group within forms, use the exposed `inputProps` from the `connect`
function and ensure you pass `name` value to the machine's context. It will
render a hidden input and ensure the value changes get propagated to the form
correctly.

```jsx {2}
const service = useMachine(radio.machine, {
  name: "fruits",
})
```

## Styling guide

Earlier, we mentioned that each radio part has a `data-part` attribute added to
them to select and style them in the DOM.

### Checked State

When the radio input is checked, the `data-state` attribute is added to the

```css
[data-part="radio"][data-state="checked|unchecked"] {
  /* styles for radio checked or unchecked state */
}

[data-part="radio-control"][data-state="checked|unchecked"] {
  /* styles for radio checked or unchecked state */
}

[data-part="radio-label"][data-state="checked|unchecked"] {
  /* styles for radio checked or unchecked state */
}
```

### Focused State

When the radio input is focused, the `data-focus` attribute is added to the
root, control and label parts.

```css
[data-part="radio"][data-focus] {
  /* styles for radio focus state */
}

[data-part="radio-control"][data-focus] {
  /* styles for radio control focus state */
}

[data-part="radio-label"][data-focus] {
  /* styles for radio label focus state */
}
```

### Disabled State

When the radio is disabled, the `data-disabled` attribute is added to the root,
control and label parts.

```css
[data-part="radio"][data-disabled] {
  /* styles for radio disabled state */
}

[data-part="radio-control"][data-disabled] {
  /* styles for radio control disabled state */
}

[data-part="radio-label"][data-disabled] {
  /* styles for radio label disabled state */
}
```

### Invalid State

When the radio is invalid, the `data-invalid` attribute is added to the root,
control and label parts.

```css
[data-part="radio"][data-invalid] {
  /* styles for radio invalid state */
}

[data-part="radio-control"][data-invalid] {
  /* styles for radio control invalid state */
}

[data-part="radio-label"][data-invalid] {
  /* styles for radio label invalid state */
}
```

## Methods and Properties

### Machine Context

The radio group machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; label: string; indicator: string; item(value: string): string; itemLabel(value: string): string; itemControl(value: string): string; itemHiddenInput(value: string): string; }>`
Description: The ids of the elements in the radio. Useful for composition.

**`value`**
Type: `string`
Description: The controlled value of the radio group

**`defaultValue`**
Type: `string`
Description: The initial value of the checked radio when rendered.
Use when you don't need to control the value of the radio group.

**`name`**
Type: `string`
Description: The name of the input fields in the radio
(Useful for form submission).

**`form`**
Type: `string`
Description: The associate form of the underlying input.

**`disabled`**
Type: `boolean`
Description: If `true`, the radio group will be disabled

**`readOnly`**
Type: `boolean`
Description: Whether the checkbox is read-only

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function called once a radio is checked

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: Orientation of the radio group

**`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 radio group `api` exposes the following methods:

**`value`**
Type: `string`
Description: The current value of the radio group

**`setValue`**
Type: `(value: string) => void`
Description: Function to set the value of the radio group

**`clearValue`**
Type: `() => void`
Description: Function to clear the value of the radio group

**`focus`**
Type: `() => void`
Description: Function to focus the radio group

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state details of a radio input

## Accessibility

Adheres to the
[Radio Group WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/radiobutton)

### Keyboard Interactions

**`Tab`**
Description: Moves focus to either the checked radio item or the first radio item in the group.

**`Space`**
Description: When focus is on an unchecked radio item, checks it.

**`ArrowDown`**
Description: Moves focus and checks the next radio item in the group.

**`ArrowRight`**
Description: Moves focus and checks the next radio item in the group.

**`ArrowUp`**
Description: Moves focus to the previous radio item in the group.

**`ArrowLeft`**
Description: Moves focus to the previous radio item in the group.



# Range Slider

A range slider is a multi-thumb slider used to select a range between two
numbers.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/slider)
[Logic Visualizer](https://zag-visualizer.vercel.app/slider)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/slider)



**Features**

- Fully managed keyboard navigation.
- Supports touch or click on track to update value.
- Supports Right-to-Left directionality.
- Support for horizontal and vertical orientations.
- Prevents text selection while dragging.

## Installation

To use the range slider machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/slider @zag-js/react
# or
yarn add @zag-js/slider @zag-js/react
```


This command will install the framework agnostic range slider logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the 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

First, import the range slider package into your project

```jsx
import * as rangeSlider from "@zag-js/slider"
```

The range slider package exports two key functions:

- `machine` — The state machine logic for the slider widget as described in the
  WAI-ARIA spec.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
range slider machine in your project 🔥

```jsx
import * as slider from "@zag-js/slider"
import { useMachine, normalizeProps } from "@zag-js/react"

export function RangeSlider() {
  const service = useMachine(slider.machine, {
    id: "1",
    name: "quantity",
    defaultValue: [10, 60],
  })

  const api = slider.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getControlProps()}>
        <div {...api.getTrackProps()}>
          <div {...api.getRangeProps()} />
        </div>
        {api.value.map((_, index) => (
          <div key={index} {...api.getThumbProps({ index })}>
            <input {...api.getHiddenInputProps({ index })} />
          </div>
        ))}
      </div>
    </div>
  )
}
```


## Changing the orientation

By default, the slider is assumed to be horizontal. To change the orientation to
vertical, set the `orientation` property in the machine's context to `vertical`.

In this mode, the slider will use the arrow up and down keys to
increment/decrement its value.

> Don't forget to change the styles of the vertical slider by specifying its
> height

```jsx {2}
const service = useMachine(slider.machine, {
  orientation: "vertical",
})
```

## Setting the initial value

```jsx {2}
const service = useMachine(slider.machine, {
  defaultValue: [30, 60],
})
```

## Specifying the minimum and maximum

By default, the minimum is `0` and the maximum is `100`. If that's not what you
want, you can easily specify different bounds by changing the values of the min
and/or max attributes.

For example, to ask the user for a value between `-10` and `10`, you can use:

```jsx {2-3}
const service = useMachine(slider.machine, {
  min: -10,
  max: 10,
})
```

## Setting the value's granularity

By default, the granularity, is `1`, meaning that the value is always an
integer. You can change the step attribute to control the granularity.

For example, If you need a value between `5` and `10`, accurate to two decimal
places, you should set the value of step to `0.01`:

```jsx {4}
const service = useMachine(slider.machine, {
  min: 5,
  max: 10,
  step: 0.01,
})
```

## Listening for changes

When the slider value changes, the `onValueChange` and `onValueChangeEnd`
callbacks are invoked. You can use this to setup custom behaviors in your app.

```jsx {2-7}
const service = useMachine(slider.machine, {
  onValueChange(details) {
    // details => { values: number[] }
    console.log("value changing to:", details)
  },
  onValueChangeEnd(details) {
    // details => { values: number[] }
    console.log("value has changed to:", details)
  },
})
```

## Preventing thumb overlap

By default, the range slider thumbs are allowed to overlap when their values are
equal. To prevent this, use the `minStepsBetweenThumbs` to avoid thumbs with
equal values.

```jsx {2}
const service = useMachine(slider.machine, {
  minStepsBetweenThumbs: 1,
})
```

## Usage within forms

To use slider within forms, use the exposed `getInputProps` from the `connect`
function and ensure you pass `name` value to the machine's context. It will
render a hidden input for each value and ensure the value changes get propagated
to the form correctly.

```jsx {2}
const service = useMachine(slider.machine, {
  name: "quantity",
})
```

## RTL Support

The slider has built-in support for RTL alignment and interaction. In the RTL
mode, operations are performed from right to left, meaning, the left arrow key
will increment and the right arrow key will decrement.

To enable RTL support, pass the `dir: rtl` context property

```jsx {2}
const service = useMachine(slider.machine, {
  dir: "rtl",
})
```

> While we take care of the interactions in RTL mode, you'll have to ensure you
> apply the correct CSS styles to flip the layout.

## Styling guide

Earlier, we mentioned that each slider part has a `data-part` attribute added to
them to select and style them in the DOM.

### Focused State

When the slider thumb is focused, the `data-focus` attribute is added to the
root, control, thumb and label parts.

```css
[data-part="root"][data-focus] {
  /* styles for root focus state */
}

[data-part="thumb"]:focus {
  /* styles for thumb focus state */
}

[data-part="control"][data-focus] {
  /* styles for control focus state */
}

[data-part="track"][data-focus] {
  /* styles for track focus state */
}

[data-part="range"][data-focus] {
  /* styles for range focus state */
}
```

### Disabled State

When the slider is disabled, the `data-disabled` attribute is added to the root,
label, control and thumb.

```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="value-text"][data-disabled] {
  /* styles for output disabled state */
}

[data-part="thumb"][data-disabled] {
  /* styles for thumb disabled state */
}

[data-part="range"][data-disabled] {
  /* styles for range disabled state */
}
```

### Orientation

```css
[data-part="root"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}

[data-part="thumb"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}

[data-part="track"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}
```

## Methods and Properties

### Machine Context

The slider machine exposes the following context properties:



### Machine API

The slider `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="slider" />

## Accessibility

Adheres to the
[Slider WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slidertwothumb).

### Keyboard Interactions

**`ArrowRight`**
Description: <span>Increments the focused thumb based on defined step</span>

**`ArrowLeft`**
Description: <span>Decrements the focused thumb based on defined step</span>

**`ArrowUp`**
Description: <span>Increases the focused thumb by the step amount.</span>

**`ArrowDown`**
Description: <span>Decreases the focused thumb by the step amount.</span>

**`PageUp`**
Description: <span>Increases the focused thumb value by a larger step</span>

**`PageDown`**
Description: <span>Decreases the focused thumb value by a larger step</span>

**`Shift + ArrowUp`**
Description: <span>Increases the focused thumb value by a larger step</span>

**`Shift + ArrowDown`**
Description: <span>Decreases the focused thumb value by a larger step</span>

**`Home`**
Description: Sets the focused thumb value to its minimum.

**`End`**
Description: Sets the focused thumb value to its maximum.



# Rating Group

Rating group allows a user to assign rating to an item within a product.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/rating-group)
[Logic Visualizer](https://zag-visualizer.vercel.app/rating-group)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/rating-group)



**Features**

- Support for syncing `disabled` state of with `fieldset` element
- Support for form `reset` events

## Installation

To use the rating group machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/rating-group @zag-js/react
# or
yarn add @zag-js/rating-group @zag-js/react
```


This command will install the framework agnostic rating logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the rating 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

First, import the rating package into your project

```jsx
import * as rating from "@zag-js/rating-group"
```

The rating package exports two key functions:

- `machine` — The state machine logic for the rating widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
rating machine in your project 🔥

```jsx
import * as rating from "@zag-js/rating-group"
import { useMachine, normalizeProps } from "@zag-js/react"
import { HalfStar, Star } from "./icons"

function Rating() {
  const service = useMachine(rating.machine, { id: "1" })

  const api = rating.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Rate:</label>
      <div {...api.getControlProps()}>
        {api.items.map((index) => {
          const state = api.getItemState({ index })
          return (
            <span key={index} {...api.getItemProps({ index })}>
              {state.half ? <HalfStar /> : <Star />}
            </span>
          )
        })}
      </div>
      <input {...api.getHiddenInputProps()} />
    </div>
  )
}
```


## Disabling the rating group

To make rating disabled, set the context's `disabled` property to true

```jsx {2}
const service = useMachine(rating.machine, {
  disabled: true,
})
```

## Making the rating readonly

To make rating readonly, set the context's `readOnly` property to true

```jsx {2}
const service = useMachine(rating.machine, {
  readOnly: true,
})
```

## Setting the initial value

To set the rating's initial value, set the context's `value` property.

```jsx {2}
const service = useMachine(rating.machine, {
  defaultValue: 2.5,
})
```

## Listening for changes

When the rating value changes, the `onValueChange` callback is invoked.

```jsx {2-7}
const service = useMachine(rating.machine, {
  onValueChange({ value }) {
    console.log("rating value is:", value)
    // '1' | '2.5' | '4'
  },
})
```

## Usage within forms

To use rating within forms, use the exposed `inputProps` from the `connect`
function and ensure you pass `name` value to the machine's context. It will
render a hidden input and ensure the value changes get propagated to the form
correctly.

```jsx {2}
const service = useMachine(rating.machine, {
  name: "rating",
})
```

## Styling guide

Earlier, we mentioned that each rating part has a `data-part` attribute added to
them to select and style them in the DOM.

### Disabled State

When the rating is disabled, the `data-disabled` attribute is added to the
rating, control and label parts.

```css
[data-part="rating"][data-disabled] {
  /* styles for rating disabled state */
}

[data-part="label"][data-disabled] {
  /* styles for rating control disabled state */
}

[data-part="input"][data-disabled] {
  /* styles for rating label disabled state */
}
```

### Checked State

When the rating is checked, the `data-checked` attribute is added to the rating
part.

```css
[data-part="rating"][data-checked] {
  /* styles for rating checked state */
}
```

### Readonly State

When the rating is readonly, the `data-readonly` attribute is added to the
rating part.

```css
[data-part="rating"][data-readonly] {
  /* styles for rating readonly state */
}
```

### Highlighted

When a rating is highlighted, the `data-highlighted` attribute is added to the
rating part.

```css
[data-part="rating"][data-highlighted] {
  /* styles for highlighted rating */
}
```

### Half rating

When a rating is half, the `data-half` attribute is added to the rating part.

```css
[data-part="rating"][data-half] {
  /* styles for half rating */
}
```

## Methods and Properties

### Machine Context

The rating group machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; label: string; hiddenInput: string; control: string; item(id: string): string; }>`
Description: The ids of the elements in the rating. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`count`**
Type: `number`
Description: The total number of ratings.

**`name`**
Type: `string`
Description: The name attribute of the rating element (used in forms).

**`form`**
Type: `string`
Description: The associate form of the underlying input element.

**`value`**
Type: `number`
Description: The controlled value of the rating

**`defaultValue`**
Type: `number`
Description: The initial value of the rating when rendered.
Use when you don't need to control the value of the rating.

**`readOnly`**
Type: `boolean`
Description: Whether the rating is readonly.

**`disabled`**
Type: `boolean`
Description: Whether the rating is disabled.

**`required`**
Type: `boolean`
Description: Whether the rating is required.

**`allowHalf`**
Type: `boolean`
Description: Whether to allow half stars.

**`autoFocus`**
Type: `boolean`
Description: Whether to autofocus the rating.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function to be called when the rating value changes.

**`onHoverChange`**
Type: `(details: HoverChangeDetails) => void`
Description: Function to be called when the rating value is hovered.

**`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 rating group `api` exposes the following methods:

**`setValue`**
Type: `(value: number) => void`
Description: Sets the value of the rating group

**`clearValue`**
Type: `() => void`
Description: Clears the value of the rating group

**`hovering`**
Type: `boolean`
Description: Whether the rating group is being hovered

**`value`**
Type: `number`
Description: The current value of the rating group

**`hoveredValue`**
Type: `number`
Description: The value of the currently hovered rating

**`count`**
Type: `number`
Description: The total number of ratings

**`items`**
Type: `number[]`
Description: The array of rating values. Returns an array of numbers from 1 to the max value.

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state of a rating item

### Data Attributes

**`Label`**

**`data-scope`**: rating-group
**`data-part`**: label
**`data-disabled`**: Present when disabled

**`Control`**

**`data-scope`**: rating-group
**`data-part`**: control
**`data-readonly`**: Present when read-only
**`data-disabled`**: Present when disabled

**`Item`**

**`data-scope`**: rating-group
**`data-part`**: item
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-checked`**: Present when checked
**`data-highlighted`**: Present when highlighted
**`data-half`**: 

## Accessibility

### Keyboard Interactions

**`ArrowRight`**
Description: Moves focus to the next star, increasing the rating value based on the `allowHalf` property.

**`ArrowLeft`**
Description: Moves focus to the previous star, decreasing the rating value based on the `allowHalf` property.

**`Enter`**
Description: Selects the focused star in the rating group.



# Segmented Control

A Segmented control allows users to make a single selection from multiple
exclusive options, providing a visually distinct and intuitive way of
interacting with radio inputs.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/radio-group)
[Logic Visualizer](https://zag-visualizer.vercel.app/segmented-control)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/segmented-control)



**Features**

- Syncs with `disabled` state of fieldset
- Syncs with form `reset` events
- Can programmatically set segmented control value
- Can programmatically focus and blur segmented control items

## Installation

To use segmented control add the radio machine to your project, run the
following command in your command line:

```bash
npm install @zag-js/radio-group @zag-js/react
# or
yarn add @zag-js/radio-group @zag-js/react
```


This command will install the framework agnostic radio group logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the segmented control 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

First, import the radio group package into your project

```jsx
import * as radio from "@zag-js/radio-group"
```

The radio package exports two key functions:

- `machine` — The state machine logic for the radio widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
radio machine in your project 🔥

```jsx
import * as radio from "@zag-js/radio-group"
import { useMachine, normalizeProps } from "@zag-js/react"

const items = [
  { label: "React", value: "react" },
  { label: "Angular", value: "ng" },
  { label: "Vue", value: "vue" },
  { label: "Svelte", value: "svelte" },
]

function Radio() {
  const service = useMachine(radio.machine, { id: "1" })

  const api = radio.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getIndicatorProps()} />
      {items.map((opt) => (
        <label key={opt.value} {...api.getItemProps({ value: opt.value })}>
          <span {...api.getItemTextProps({ value: opt.value })}>
            {opt.label}
          </span>
          <input {...api.getItemHiddenInputProps({ value: opt.value })} />
        </label>
      ))}
    </div>
  )
}
```


## Disabling the segmented control

To make a segmented control disabled, set the context's `disabled` property to
true

```jsx {2}
const service = useMachine(radio.machine, {
  disabled: true,
})
```

## Making the segmented control readonly

To make a segmented control readonly, set the context's `readOnly` property to
true

```jsx {2}
const service = useMachine(radio.machine, {
  readOnly: true,
})
```

## Setting the initial value

To set the segmented control's initial value, set the context's `value` property
to the value of the radio item to be selected by default

```jsx {2}
const service = useMachine(radio.machine, {
  value: "apple",
})
```

## Listening for changes

When the segmented control value changes, the `onValueChange` callback is
invoked.

```jsx {2-7}
const service = useMachine(radio.machine, {
  onValueChange(details) {
    // details => { value: string }
    console.log("segmented control value is:", details.value)
  },
})
```

## Usage within forms

To use segmented control within forms, use the exposed `inputProps` from the
`connect` function and ensure you pass `name` value to the machine's context. It
will render a hidden input and ensure the value changes get propagated to the
form correctly.

```jsx {2}
const service = useMachine(radio.machine, {
  name: "fruits",
})
```

## Styling guide

Earlier, we mentioned that each segmented control part has a `data-part`
attribute added to them to select and style them in the DOM.

### Indicator

Style the segmented control Indicator through the `indicator` part.

```css
[data-part="indicator"] {
  /* styles for indicator */
}
```

### Focused State

When the radio input is focused, the `data-focus` attribute is added to the root
and label parts.

```css
[data-part="radio"][data-focus] {
  /* styles for radio focus state */
}

[data-part="radio-label"][data-focus] {
  /* styles for radio label focus state */
}
```

### Disabled State

When the radio is disabled, the `data-disabled` attribute is added to the root
and label parts.

```css
[data-part="radio"][data-disabled] {
  /* styles for radio disabled state */
}

[data-part="radio-label"][data-disabled] {
  /* styles for radio label disabled state */
}
```

### Invalid State

When the radio is invalid, the `data-invalid` attribute is added to the root and
label parts.

```css
[data-part="radio"][data-invalid] {
  /* styles for radio invalid state */
}

[data-part="radio-label"][data-invalid] {
  /* styles for radio label invalid state */
}
```

## Methods and Properties

### Machine Context

The radio group machine exposes the following context properties:



### Machine API

The radio group `api` exposes the following methods:



### Data Attributes

<DataAttrTable name="radio-group" />



# Select

A Select component allows users pick a value from predefined options.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/select)
[Logic Visualizer](https://zag-visualizer.vercel.app/select)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/select)



**Features**

- Support for selecting a single or multiple option
- Keyboard support for opening the listbox using the arrow keys, including
  automatically focusing the first or last item.
- Support for looping keyboard navigation.
- Support for selecting an item on blur.
- Typeahead to allow selecting options by typing text, even without opening the
  listbox
- Support for Right to Left direction.

## Installation

To use the select machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/select @zag-js/react
# or
yarn add @zag-js/select @zag-js/react
```


This command will install the framework agnostic menu logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the select 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

First, import the select package into your project

```jsx
import * as select from "@zag-js/select"
```

The select package exports these functions:

- `machine` — The state machine logic for the select.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.
- `collection` - The function that creates a
  [collection interface](/overview/collection) from an array of items.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
select machine in your project 🔥

```jsx
import * as select from "@zag-js/select"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import { useId, useRef } from "react"

const selectData = [
  { label: "Nigeria", value: "NG" },
  { label: "Japan", value: "JP" },
  { label: "Korea", value: "KO" },
  { label: "Kenya", value: "KE" },
  { label: "United Kingdom", value: "UK" },
  { label: "Ghana", value: "GH" },
  { label: "Uganda", value: "UG" },
]

export function Select() {
  const collection = select.collection({
    items: selectData,
    itemToString: (item) => item.label,
    itemToValue: (item) => item.value,
  })

  const service = useMachine(select.machine, {
    id: useId(),
    collection,
  })

  const api = select.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getControlProps()}>
        <label {...api.getLabelProps()}>Label</label>
        <button {...api.getTriggerProps()}>
          {api.valueAsString || "Select option"}
        </button>
      </div>

      <Portal>
        <div {...api.getPositionerProps()}>
          <ul {...api.getContentProps()}>
            {selectData.map((item) => (
              <li key={item.value} {...api.getItemProps({ item })}>
                <span>{item.label}</span>
                <span {...api.getItemIndicatorProps({ item })}>✓</span>
              </li>
            ))}
          </ul>
        </div>
      </Portal>
    </div>
  )
}
```


## Setting the initial value

To set the initial value of the select, pass the `value` property to the select
machine's context.

> The `value` property must be an array of strings. If selecting a single value,
> pass an array with a single string.

```jsx {13}
const collection = select.collection({
  items: [
    { label: "Nigeria", value: "ng" },
    { label: "Ghana", value: "gh" },
    { label: "Kenya", value: "ke" },
    //...
  ],
})

const service = useMachine(select.machine, {
  id: useId(),
  collection,
  defaultValue: ["ng"],
})
```

## Selecting multiple values

To allow selecting multiple values, set the `multiple` property in the machine's
context to `true`.

```jsx {5}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  multiple: true,
})
```

## Using a custom object format

By default, the select 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 = select.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(select.machine, {
  id: useId(),
  collection,
})
```

## Usage within a form

To use select within a form, you'll need to:

- Pass the `name` property to the select machine's context
- Render a hidden `select` element using `api.getSelectProps()`

```jsx
import * as select from "@zag-js/select"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import { useId } from "react"

const selectData = [
  { label: "Nigeria", value: "NG" },
  { label: "Japan", value: "JP" },
  { label: "Korea", value: "KO" },
  { label: "Kenya", value: "KE" },
  { label: "United Kingdom", value: "UK" },
  { label: "Ghana", value: "GH" },
  { label: "Uganda", value: "UG" },
]

export function SelectWithForm() {
  const service = useMachine(select.machine, {
    id: useId(),
    collection: select.collection({ items: selectData }),
    name: "country",
  })

  const api = select.connect(service, normalizeProps)

  return (
    <form>
      {/* Hidden select */}
      <select {...api.getHiddenSelectProps()}>
        {selectData.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>

      {/* Custom Select */}
      <div {...api.getControlProps()}>
        <label {...api.getLabelProps()}>Label</label>
        <button type="button" {...api.getTriggerProps()}>
          <span>{api.valueAsString || "Select option"}</span>
          <CaretIcon />
        </button>
      </div>

      <Portal>
        <div {...api.getPositionerProps()}>
          <ul {...api.getContentProps()}>
            {selectData.map((item) => (
              <li key={item.value} {...api.getItemProps({ item })}>
                <span>{item.label}</span>
                <span {...api.getItemIndicatorProps({ item })}>✓</span>
              </li>
            ))}
          </ul>
        </div>
      </Portal>
    </form>
  )
}
```


## Disabling the select

To disable the select, set the `disabled` property in the machine's context to
`true`.

```jsx {4}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  disabled: true,
})
```

## Disabling an item

To make a combobox option disabled, pass the `isItemDisabled` property to the
collection function.

```jsx {3-4}
const collection = select.collection({
  items: countries,
  isItemDisabled(item) {
    return item.disabled
  },
})

const service = useMachine(select.machine, {
  id: useId(),
  collection,
})
```

## Close on select

This behaviour ensures that the menu is closed when an item is selected and is
`true` by default. It's only concerned with when an item is selected with
pointer, space key or enter key. To disable the behaviour, set the
`closeOnSelect` property in the machine's context to `false`.

```jsx {4}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  closeOnSelect: false,
})
```

## Looping the keyboard navigation

When navigating with the select using the arrow down and up keys, the select
stops at the first and last options. If you need want the navigation to loop
back to the first or last option, set the `loop: true` in the machine's context.

```jsx {4}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  loop: 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(select.machine, {
  id: useId(),
  onHighlightChange(details) {
    // details => { highlightedValue: string | null, highlightedItem: CollectionItem | null }
    console.log(details)
  },
})
```

## 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-6}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  onValueChange(details) {
    // details => { value: string[], items: Item[] }
    console.log(details)
  },
})
```

## Listening for open and close events

When the select is opened or closed, the `onOpenChange` callback is called. You
can listen for these events and do something with it.

```jsx {4-7}
const service = useMachine(select.machine, {
  id: useId(),
  collection,
  onOpenChange(details) {
    // details => { open: boolean }
    console.log("Select opened")
  },
})
```

## Usage with large data

Combine the select machine with the virtualization library like `react-window`
or `@tanstack/react-virtual` to handle large data.

Here's an example using `@tanstack/react-virtual`:

```jsx
function Demo() {
  const selectData = []

  const contentRef = useRef(null)

  const rowVirtualizer = useVirtualizer({
    count: selectData.length,
    getScrollElement: () => contentRef.current,
    estimateSize: () => 32,
  })

  const service = useMachine(select.machine, {
    id: useId(),
    collection,
    scrollToIndexFn(details) {
      rowVirtualizer.scrollToIndex(details.index, {
        align: "center",
        behavior: "auto",
      })
    },
  })

  const api = select.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {/* ... */}
      <Portal>
        <div {...api.getPositionerProps()}>
          <div ref={contentRef} {...api.getContentProps()}>
            <div
              style={{
                height: `${rowVirtualizer.getTotalSize()}px`,
                width: "100%",
                position: "relative",
              }}
            >
              {rowVirtualizer.getVirtualItems().map((virtualItem) => {
                const item = selectData[virtualItem.index]
                return (
                  <div
                    key={item.value}
                    {...api.getItemProps({ item })}
                    style={{
                      position: "absolute",
                      top: 0,
                      left: 0,
                      width: "100%",
                      height: `${virtualItem.size}px`,
                      transform: `translateY(${virtualItem.start}px)`,
                      whiteSpace: "nowrap",
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                    }}
                  >
                    <span>{item.label}</span>
                    <span {...api.getItemIndicatorProps({ item })}>✓</span>
                  </div>
                )
              })}
            </div>
          </div>
        </div>
      </Portal>
    </div>
  )
}
```

## Usage within dialog

When using the select within a dialog, avoid rendering the select in a `Portal`
or `Teleport`. This is because the dialog will trap focus within it, and the
select will be rendered outside the dialog.

## Styling guide

Earlier, we mentioned that each select part has a `data-part` attribute added to
them to select and style them in the DOM.

### Open and closed state

When the 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 */
}
```

### Invalid state

When the 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 select is disabled, the trigger and label is given a `data-disabled`
attribute.

```css
[data-part="trigger"][data-disabled] {
  /* styles for disabled select state */
}

[data-part="label"][data-disabled] {
  /* styles for disabled label state */
}

[data-part="item"][data-disabled] {
  /* styles for disabled option state */
}
```

> Optionally, when an item is disabled, it is given a `data-disabled` attribute.

### 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 select state */
}
```

## Methods and Properties

### Machine Context

The select machine exposes the following context properties:

**`collection`**
Type: `ListCollection<T>`
Description: The item collection

**`ids`**
Type: `Partial<{ root: string; content: string; control: string; trigger: string; clearTrigger: string; label: string; hiddenSelect: string; positioner: string; item(id: string | number): string; itemGroup(id: string | number): string; itemGroupLabel(id: string | number): string; }>`
Description: The ids of the elements in the select. Useful for composition.

**`name`**
Type: `string`
Description: The `name` attribute of the underlying select.

**`form`**
Type: `string`
Description: The associate form of the underlying select.

**`disabled`**
Type: `boolean`
Description: Whether the select is disabled

**`invalid`**
Type: `boolean`
Description: Whether the select is invalid

**`readOnly`**
Type: `boolean`
Description: Whether the select is read-only

**`required`**
Type: `boolean`
Description: Whether the select is required

**`closeOnSelect`**
Type: `boolean`
Description: Whether the select should close after an item is selected

**`onHighlightChange`**
Type: `(details: HighlightChangeDetails<T>) => void`
Description: The callback fired when the highlighted item changes.

**`onValueChange`**
Type: `(details: ValueChangeDetails<T>) => void`
Description: The callback fired when the selected item changes.

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Function called when the popup is opened

**`positioning`**
Type: `PositioningOptions`
Description: The positioning options of the menu.

**`value`**
Type: `string[]`
Description: The controlled keys of the selected items

**`defaultValue`**
Type: `string[]`
Description: The initial default value of the select when rendered.
Use when you don't need to control the value of the select.

**`highlightedValue`**
Type: `string`
Description: The controlled key of the highlighted item

**`defaultHighlightedValue`**
Type: `string`
Description: The initial value of the highlighted item when opened.
Use when you don't need to control the highlighted value of the select.

**`loopFocus`**
Type: `boolean`
Description: Whether to loop the keyboard navigation through the options

**`multiple`**
Type: `boolean`
Description: Whether to allow multiple selection

**`open`**
Type: `boolean`
Description: Whether the select menu is open

**`defaultOpen`**
Type: `boolean`
Description: Whether the select's open state is controlled by the user

**`scrollToIndexFn`**
Type: `(details: ScrollToIndexDetails) => void`
Description: Function to scroll to a specific index

**`composite`**
Type: `boolean`
Description: Whether the select is a composed with other composite widgets like tabs or combobox

**`deselectable`**
Type: `boolean`
Description: Whether the value can be cleared by clicking the selected item.

**Note:** this is only applicable for single selection

**`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 select `api` exposes the following methods:

**`focused`**
Type: `boolean`
Description: Whether the select is focused

**`open`**
Type: `boolean`
Description: Whether the select is open

**`empty`**
Type: `boolean`
Description: Whether the select value is empty

**`highlightedValue`**
Type: `string`
Description: The value of the highlighted item

**`highlightedItem`**
Type: `V`
Description: The highlighted item

**`highlightValue`**
Type: `(value: string) => void`
Description: Function to highlight a value

**`selectedItems`**
Type: `V[]`
Description: The selected items

**`hasSelectedItems`**
Type: `boolean`
Description: Whether there's a selected option

**`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

**`selectAll`**
Type: `() => void`
Description: Function to select all values

**`setValue`**
Type: `(value: string[]) => void`
Description: Function to set the value of the select

**`clearValue`**
Type: `(value?: string) => void`
Description: Function to clear the value of the select.
If a value is provided, it will only clear that value, otherwise, it will clear all values.

**`focus`**
Type: `() => void`
Description: Function to focus on the select input

**`getItemState`**
Type: `(props: ItemProps<any>) => ItemState`
Description: Returns the state of a select item

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open or close the select

**`collection`**
Type: `ListCollection<V>`
Description: Function to toggle the select

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => void`
Description: Function to set the positioning options of the select

**`multiple`**
Type: `boolean`
Description: Whether the select allows multiple selections

**`disabled`**
Type: `boolean`
Description: Whether the select is disabled

### Data Attributes

**`Root`**

**`data-scope`**: select
**`data-part`**: root
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`Label`**

**`data-scope`**: select
**`data-part`**: label
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`Control`**

**`data-scope`**: select
**`data-part`**: control
**`data-state`**: "open" | "closed"
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid

**`ValueText`**

**`data-scope`**: select
**`data-part`**: value-text
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`Trigger`**

**`data-scope`**: select
**`data-part`**: trigger
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only
**`data-placement`**: The placement of the trigger
**`data-placeholder-shown`**: Present when placeholder is shown

**`Indicator`**

**`data-scope`**: select
**`data-part`**: indicator
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`Item`**

**`data-scope`**: select
**`data-part`**: item
**`data-value`**: The value of the item
**`data-state`**: "checked" | "unchecked"
**`data-highlighted`**: Present when highlighted
**`data-disabled`**: Present when disabled

**`ItemText`**

**`data-scope`**: select
**`data-part`**: item-text
**`data-state`**: "checked" | "unchecked"
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted

**`ItemIndicator`**

**`data-scope`**: select
**`data-part`**: item-indicator
**`data-state`**: "checked" | "unchecked"

**`ItemGroup`**

**`data-scope`**: select
**`data-part`**: item-group
**`data-disabled`**: Present when disabled

**`ClearTrigger`**

**`data-scope`**: select
**`data-part`**: clear-trigger
**`data-invalid`**: Present when invalid

**`Content`**

**`data-scope`**: select
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-placement`**: The placement of the content
**`data-activedescendant`**: 

## Accessibility

Adheres to the
[ListBox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox).

### Keyboard Interactions

**`Space`**
Description: <span>When focus is on trigger, opens the select and focuses the first selected item.<br />When focus is on the content, selects the highlighted item.</span>

**`Enter`**
Description: <span>When focus is on trigger, opens the select and focuses the first selected item.<br />When focus is on content, selects the focused item.</span>

**`ArrowDown`**
Description: <span>When focus is on trigger, opens the select.<br />When focus is on content, moves focus to the next item.</span>

**`ArrowUp`**
Description: <span>When focus is on trigger, opens the select.<br />When focus is on content, moves focus to the previous item.</span>

**`Esc`**
Description: <span>Closes the select and moves focus to trigger.</span>

**`A-Z + a-z`**
Description: <span>When focus is on trigger, selects the item whose label starts with the typed character.<br />When focus is on the listbox, moves focus to the next item with a label that starts with the typed character.</span>



# Signature Pad

The signature pad component allows users to draw handwritten signatures using
touch or pointer devices. The signature can be saved as an image or cleared.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/signature-pad)
[Logic Visualizer](https://zag-visualizer.vercel.app/signature-pad)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/signature-pad)



**Features**

- Draw signatures using touch or pointer devices.
- Save the signature as an image.
- Clear the signature.

## Installation

To use the signature pad machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/signature-pad @zag-js/react
# or
yarn add @zag-js/signature-pad @zag-js/react
```


This command will install the framework agnostic signature pad logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the signature pad 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

First, import the signature pad package into your project

```jsx
import * as signaturePad from "@zag-js/signature-pad"
```

The signature pad package exports two key functions:

- `machine` — The state machine logic for the signature pad widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
signature pad machine in your project 🔥

```jsx
import { normalizeProps, useMachine } from "@zag-js/react"
import * as signaturePad from "@zag-js/signature-pad"
import { useId, useState } from "react"

export function SignaturePad() {
  const service = useMachine(signaturePad.machine, {
    id: useId(),
  })

  const api = signaturePad.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Signature Pad</label>

      <div {...api.getControlProps()}>
        <svg {...api.getSegmentProps()}>
          {api.paths.map((path, i) => (
            <path key={i} {...api.getSegmentPathProps({ path })} />
          ))}
          {api.currentPath && (
            <path {...api.getSegmentPathProps({ path: api.currentPath })} />
          )}
        </svg>

        <button {...api.getClearTriggerProps()}>X</button>

        <div {...api.getGuideProps()} />
      </div>
    </div>
  )
}
```


## Listening to drawing events

The signature pad component emits the following events:

- `onDraw`: Emitted when the user is drawing the signature.
- `onDrawEnd`: Emitted when the user stops drawing the signature.

```jsx
const service = useMachine(signature.machine, {
  onDraw(details) {
    // details => { path: string[] }
    console.log("Drawing signature", details)
  },
  onDrawEnd(details) {
    // details => { path: string[], toDataURL: () => string }
    console.log("Signature drawn", details)
  },
})
```

## Clearing the signature

To clear the signature, use the `api.clear()`, or render the clear trigger
button.

```jsx
<button onClick={() => api.clear()}>Clear</button>
```

## Rendering an image preview

Use the `api.getDataUrl()` method to get the signature as a data URL and render
it as an image.

> You can also leverage the `onDrawEnd` event to get the signature data URL.

```jsx
const service = useMachine(signature.machine, {
  onDrawEnd(details) {
    details.getDataUrl("image/png").then((url) => {
      // set the image URL in local state
      setImageURL(url)
    })
  },
})
```

Next, render the image preview using the URL.

```jsx
<img src={imageURL} alt="Signature" />
```

## Changing the stroke color

To change the stroke color, set the `drawing.fill` option to a valid CSS color.

> Note: You can't use a css variable as the stroke color.

```jsx
const service = useMachine(signature.machine, {
  drawing: {
    fill: "red",
  },
})
```

## Changing the stroke width

To change the stroke width, set the `drawing.size` option to a number.

```jsx
const service = useMachine(signature.machine, {
  drawing: {
    size: 5,
  },
})
```

## Simulating pressure sensitivity

Pressure sensitivity is disabled by default. To enable it, set the
`drawing.simulatePressure` option to `true`.

```jsx
const service = useMachine(signature.machine, {
  drawing: {
    simulatePressure: true,
  },
})
```

## Usage in forms

To use the signature pad in a form, set the `name` context property.

```jsx
const service = useMachine(signature.machine, {
  name: "signature",
})
```

Then, render the hidden input element using `api.getHiddenInputProps()`.

```jsx
<input {...api.getHiddenInputProps({ value: imageURL })} />
```

## Disabling the signature pad

Set the `disabled` context property to `true` to disable the signature pad.

```jsx
const service = useMachine(signature.machine, {
  disabled: true,
})
```

## Making the signature pad read-only

Set the `readOnly` context property to `true` to make the signature pad
read-only.

```jsx
const service = useMachine(signature.machine, {
  readOnly: true,
})
```

## Methods and Properties

The signature pad `api` exposes the following methods and properties:

### Machine Context

The signature pad machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; control: string; hiddenInput: string; label: string; }>`
Description: The ids of the signature pad elements. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: The translations of the signature pad. Useful for internationalization.

**`onDraw`**
Type: `(details: DrawDetails) => void`
Description: Callback when the signature pad is drawing.

**`onDrawEnd`**
Type: `(details: DrawEndDetails) => void`
Description: Callback when the signature pad is done drawing.

**`drawing`**
Type: `DrawingOptions`
Description: The drawing options.

**`disabled`**
Type: `boolean`
Description: Whether the signature pad is disabled.

**`required`**
Type: `boolean`
Description: Whether the signature pad is required.

**`readOnly`**
Type: `boolean`
Description: Whether the signature pad is read-only.

**`name`**
Type: `string`
Description: The name of the signature pad. 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 signature pad `api` exposes the following methods:

**`empty`**
Type: `boolean`
Description: Whether the signature pad is empty.

**`drawing`**
Type: `boolean`
Description: Whether the user is currently drawing.

**`currentPath`**
Type: `string`
Description: The current path being drawn.

**`paths`**
Type: `string[]`
Description: The paths of the signature pad.

**`getDataUrl`**
Type: `(type: DataUrlType, quality?: number) => Promise<string>`
Description: Returns the data URL of the signature pad.

**`clear`**
Type: `() => void`
Description: Clears the signature pad.

### Data Attributes

**`Label`**

**`data-scope`**: signature-pad
**`data-part`**: label
**`data-disabled`**: Present when disabled

**`Root`**

**`data-scope`**: signature-pad
**`data-part`**: root
**`data-disabled`**: Present when disabled

**`Control`**

**`data-scope`**: signature-pad
**`data-part`**: control
**`data-disabled`**: Present when disabled

**`Guide`**

**`data-scope`**: signature-pad
**`data-part`**: guide
**`data-disabled`**: Present when disabled



# Slider

A slider allows users to make selections from a range of values. Think of it as
a custom `<input type='range'/>` with the ability to achieve custom styling and
accessibility.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/slider)
[Logic Visualizer](https://zag-visualizer.vercel.app/slider)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/slider)



**Features**

- Supports centered origin (slider starting at center, instead of start
  position).
- Fully managed keyboard navigation.
- Supports touch or click on track to update value.
- Supports Right-to-Left directionality.
- Support for horizontal and vertical orientations.
- Prevents text selection while dragging.

## Installation

To use the slider machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/slider @zag-js/react
# or
yarn add @zag-js/slider @zag-js/react
```


This command will install the framework agnostic slider logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the 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

First, import the slider package into your project

```jsx
import * as slider from "@zag-js/slider"
```

The slider package exports two key functions:

- `machine` — The state machine logic for the slider widget as described in the
  WAI-ARIA spec.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
slider machine in your project 🔥

```jsx
import * as slider from "@zag-js/slider"
import { useMachine, normalizeProps } from "@zag-js/react"

export function Slider() {
  const service = useMachine(slider.machine, { id: "1", value: [0] })

  const api = slider.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div>
        <label {...api.getLabelProps()}>Slider Label</label>
        <output {...api.getValueTextProps()}>{api.value.at(0)}</output>
      </div>
      <div {...api.getControlProps()}>
        <div {...api.getTrackProps()}>
          <div {...api.getRangeProps()} />
        </div>
        {api.value.map((_, index) => (
          <div key={index} {...api.getThumbProps({ index })}>
            <input {...api.getHiddenInputProps({ index })} />
          </div>
        ))}
      </div>
    </div>
  )
}
```


## Changing the orientation

By default, the slider is assumed to be horizontal. To change the orientation to
vertical, set the `orientation` property in the machine's context to `vertical`.

In this mode, the slider will use the arrow up and down keys to
increment/decrement its value.

> Don't forget to change the styles of the vertical slider by specifying its
> height

```jsx {2}
const service = useMachine(slider.machine, {
  orientation: "vertical",
})
```

## Setting the initial value

Pass the `defaultValue` property to the machine's context to set the initial
value.

```jsx {2}
const service = useMachine(slider.machine, {
  defaultValue: [30],
})
```

## Specifying the minimum and maximum

By default, the minimum is `0` and the maximum is `100`. If that's not what you
want, you can easily specify different bounds by changing the values of the min
and/or max attributes.

For example, to ask the user for a value between `-10` and `10`, you can use:

```jsx {2-3}
const service = useMachine(slider.machine, {
  min: -10,
  max: 10,
})
```

## Setting the value's granularity

By default, the granularity, is `1`, meaning that the value is always an
integer. You can change the step attribute to control the granularity.

For example, If you need a value between `5` and `10`, accurate to two decimal
places, you should set the value of step to `0.01`:

```jsx {4}
const service = useMachine(slider.machine, {
  min: 5,
  max: 10,
  step: 0.01,
})
```

## Listening for changes

When the slider value changes, the `onValueChange` and `onValueChangeEnd`
callbacks are invoked. You can use this to setup custom behaviors in your app.

```jsx {2-7}
const service = useMachine(slider.machine, {
  onValueChange(details) {
    console.log("value is changing to:", details)
  },
  onValueChangeEnd(details) {
    console.log("value has changed to:", details)
  },
})
```

## Changing the start position

By default, the slider's "zero position" is usually at the start position (left
in LTR and right in RTL).

In scenarios where the value represents an offset (or relative value), it might
be useful to change the "zero position" to center. To do this, pass the `origin`
context property to `center`.

```jsx {2}
const service = useMachine(slider.machine, {
  origin: "center",
})
```

## Changing the thumb alignment

By default, the thumb is aligned to the start of the track. Set the
`thumbAlignment` context property to `contain` or `center`.

- `center`: the thumb will extend beyond the bounds of the slider track.
- `contain`: the thumb will be contained within the bounds of the track.

```jsx {2}
const service = useMachine(slider.machine, {
  thumbAlignment: "center",
})
```

If you use `contain` alignment, you might need to set the thumb size to prevent
any flickering.

```jsx {3}
const service = useMachine(slider.machine, {
  thumbAlignment: "contain",
  thumbSize: { width: 20, height: 20 },
})
```

## Usage within forms

To use slider within forms, use the exposed `inputProps` from the `connect`
function and ensure you pass `name` value to the machine's context. It will
render a hidden input and ensure the value changes get propagated to the form
correctly.

```jsx {2}
const service = useMachine(slider.machine, {
  name: "quantity",
})
```

## RTL Support

The slider has built-in support for RTL alignment and interaction. In the RTL
mode, operations are performed from right to left, meaning, the left arrow key
will increment and the right arrow key will decrement.

To enable RTL support, pass the `dir: rtl` context property

```jsx {2}
const service = useMachine(slider.machine, {
  dir: "rtl",
})
```

> While we take care of the interactions in RTL mode, you'll have to ensure you
> apply the correct CSS styles to flip the layout.

## Using slider marks

To show marks or ticks along the slider track, use the exposed
`api.getMarkerProps()` method to position the slider marks relative to the
track.

```jsx {11-15}
//...
<div>
  <div {...api.getControlProps()}>
    <div {...api.getTrackProps()}>
      <div {...api.getRangeProps()} />
    </div>
    {api.value.map((_, index) => (
      <div key={index} {...api.getThumbProps({ index })}>
        <input {...api.getHiddenInputProps({ index })} />
      </div>
    ))}
  </div>
  <div {...api.getMarkerGroupProps()}>
    <span {...api.getMarkerProps({ value: 10 })}>|</span>
    <span {...api.getMarkerProps({ value: 30 })}>|</span>
    <span {...api.getMarkerProps({ value: 90 })}>|</span>
  </div>
</div>
//...
```


## Styling guide

Earlier, we mentioned that each slider part has a `data-part` attribute added to
them to select and style them in the DOM.

### Focused State

When the slider thumb is focused, the `data-focus` attribute is added to the
root, control, thumb and label parts.

```css
[data-part="root"][data-focus] {
  /* styles for root focus state */
}

[data-part="thumb"]:focus {
  /* styles for thumb focus state */
}

[data-part="control"][data-focus] {
  /* styles for control focus state */
}

[data-part="track"][data-focus] {
  /* styles for track focus state */
}

[data-part="range"][data-focus] {
  /* styles for range focus state */
}
```

### Disabled State

When the slider is disabled, the `data-disabled` attribute is added to the root,
label, control and thumb.

```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="value-text"][data-disabled] {
  /* styles for output 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="range"][data-invalid] {
  /* styles for range invalid state */
}
```

### Orientation

```css
[data-part="root"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}

[data-part="thumb"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}

[data-part="track"][data-orientation="(horizontal|vertical)"] {
  /* styles for horizontal or vertical  */
}
```

### 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 slider machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; thumb(index: number): string; hiddenInput(index: number): string; control: string; track: string; range: string; label: string; valueText: string; marker(index: number): string; }>`
Description: The ids of the elements in the slider. Useful for composition.

**`aria-label`**
Type: `string[]`
Description: The aria-label of each slider thumb. Useful for providing an accessible name to the slider

**`aria-labelledby`**
Type: `string[]`
Description: The `id` of the elements that labels each slider thumb. Useful for providing an accessible name to the slider

**`name`**
Type: `string`
Description: The name associated with each slider thumb (when used in a form)

**`form`**
Type: `string`
Description: The associate form of the underlying input element.

**`value`**
Type: `number[]`
Description: The controlled value of the slider

**`defaultValue`**
Type: `number[]`
Description: The initial value of the slider when rendered.
Use when you don't need to control the value of the slider.

**`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

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function invoked when the value of the slider changes

**`onValueChangeEnd`**
Type: `(details: ValueChangeDetails) => void`
Description: Function invoked when the slider value change is done

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Description: Function invoked when the slider's focused index changes

**`getAriaValueText`**
Type: `(details: ValueTextDetails) => string`
Description: Function that returns a human readable value for the slider thumb

**`min`**
Type: `number`
Description: The minimum value of the slider

**`max`**
Type: `number`
Description: The maximum value of the slider

**`step`**
Type: `number`
Description: The step value of the slider

**`minStepsBetweenThumbs`**
Type: `number`
Description: The minimum permitted steps between multiple thumbs.

**`orientation`**
Type: `"vertical" | "horizontal"`
Description: The orientation of the slider

**`origin`**
Type: `"start" | "center"`
Description: The origin of the slider range
- "start": Useful when the value represents an absolute value
- "center": Useful when the value represents an offset (relative)

**`thumbAlignment`**
Type: `"center" | "contain"`
Description: The alignment of the slider thumb relative to the track
- `center`: the thumb will extend beyond the bounds of the slider track.
- `contain`: the thumb will be contained within the bounds of the track.

**`thumbSize`**
Type: `{ width: number; height: number; }`
Description: The slider thumbs dimensions

**`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 slider `api` exposes the following methods:

**`value`**
Type: `number[]`
Description: The value of the slider.

**`dragging`**
Type: `boolean`
Description: Whether the slider is being dragged.

**`focused`**
Type: `boolean`
Description: Whether the slider is focused.

**`setValue`**
Type: `(value: number[]) => void`
Description: Function to set the value of the slider.

**`getThumbValue`**
Type: `(index: number) => number`
Description: Returns the value of the thumb at the given index.

**`setThumbValue`**
Type: `(index: number, value: number) => void`
Description: Sets the value of the thumb at the given index.

**`getValuePercent`**
Type: `(value: number) => number`
Description: Returns the percent of the thumb at the given index.

**`getPercentValue`**
Type: `(percent: number) => number`
Description: Returns the value of the thumb at the given percent.

**`getThumbPercent`**
Type: `(index: number) => number`
Description: Returns the percent of the thumb at the given index.

**`setThumbPercent`**
Type: `(index: number, percent: number) => void`
Description: Sets the percent of the thumb at the given index.

**`getThumbMin`**
Type: `(index: number) => number`
Description: Returns the min value of the thumb at the given index.

**`getThumbMax`**
Type: `(index: number) => number`
Description: Returns the max value of the thumb at the given index.

**`increment`**
Type: `(index: number) => void`
Description: Function to increment the value of the slider at the given index.

**`decrement`**
Type: `(index: number) => void`
Description: Function to decrement the value of the slider at the given index.

**`focus`**
Type: `() => void`
Description: Function to focus the slider. This focuses the first thumb.

### Data Attributes

**`Label`**

**`data-scope`**: slider
**`data-part`**: label
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the label
**`data-invalid`**: Present when invalid
**`data-dragging`**: Present when in the dragging state
**`data-focus`**: Present when focused

**`Root`**

**`data-scope`**: slider
**`data-part`**: root
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the slider
**`data-dragging`**: Present when in the dragging state
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`ValueText`**

**`data-scope`**: slider
**`data-part`**: value-text
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the valuetext
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`Track`**

**`data-scope`**: slider
**`data-part`**: track
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-dragging`**: Present when in the dragging state
**`data-orientation`**: The orientation of the track
**`data-focus`**: Present when focused

**`Thumb`**

**`data-scope`**: slider
**`data-part`**: thumb
**`data-index`**: The index of the item
**`data-name`**: 
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the thumb
**`data-focus`**: Present when focused
**`data-dragging`**: Present when in the dragging state

**`Range`**

**`data-scope`**: slider
**`data-part`**: range
**`data-dragging`**: Present when in the dragging state
**`data-focus`**: Present when focused
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the range

**`Control`**

**`data-scope`**: slider
**`data-part`**: control
**`data-dragging`**: Present when in the dragging state
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the control
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`MarkerGroup`**

**`data-scope`**: slider
**`data-part`**: marker-group
**`data-orientation`**: The orientation of the markergroup

**`Marker`**

**`data-scope`**: slider
**`data-part`**: marker
**`data-orientation`**: The orientation of the marker
**`data-value`**: The value of the item
**`data-disabled`**: Present when disabled
**`data-state`**: 

**`DraggingIndicator`**

**`data-scope`**: slider
**`data-part`**: dragging-indicator
**`data-orientation`**: The orientation of the draggingindicator
**`data-state`**: "open" | "closed"

## Accessibility

Adheres to the
[Slider WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider).

### Keyboard Interactions

**`ArrowRight`**
Description: <span>Increments the slider based on defined step</span>

**`ArrowLeft`**
Description: <span>Decrements the slider based on defined step</span>

**`ArrowUp`**
Description: <span>Increases the value by the step amount.</span>

**`ArrowDown`**
Description: <span>Decreases the value by the step amount.</span>

**`PageUp`**
Description: <span>Increases the value by a larger step</span>

**`PageDown`**
Description: <span>Decreases the value by a larger step</span>

**`Shift + ArrowUp`**
Description: <span>Increases the value by a larger step</span>

**`Shift + ArrowDown`**
Description: <span>Decreases the value by a larger step</span>

**`Home`**
Description: Sets the value to its minimum.

**`End`**
Description: Sets the value to its maximum.



# Splitter

A splitter allow create dynamic layouts split into vertically or horizontally
arranged panes. Panes are separated by the splitter bars that allow dragging to
resize or expand/collapse them.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/splitter)
[Logic Visualizer](https://zag-visualizer.vercel.app/splitter)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/splitter)



**Features**

- Built with flexbox for flexible layout and SSR
- Support both dynamic horizontal and vertical panels
- Support multiple panels and splitters
- Support for collapsible panels
- Support for panel constraints like min and max sizes
- Programmatic control of panel sizes
- Implements the
  [Window Splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/)
  for accessibility and keyboard controls

## Installation

To use the splitter machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/splitter @zag-js/react
# or
yarn add @zag-js/splitter @zag-js/react
```


This command will install the framework agnostic splitter logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the 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

First, import the splitter package into your project

```jsx
import * as splitter from "@zag-js/splitter"
```

The splitter package exports two key functions:

- `machine` — The state machine logic for the splitter widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
splitter machine in your project 🔥

```jsx
import * as splitter from "@zag-js/splitter"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

export function Splitter() {
  const service = useMachine(splitter.machine, {
    id: useId(),
    defaultSize: [
      { id: "a", size: 50 },
      { id: "b", size: 50 },
    ],
  })

  const api = slider.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getPanelProps({ id: "a" })}>
        <p>A</p>
      </div>
      <div {...api.getResizeTriggerProps({ id: "a:b" })} />
      <div {...api.getPanelProps({ id: "b" })}>
        <p>B</p>
      </div>
    </div>
  )
}
```


## Setting the initial size

To set the initial size of the splitter panels, use the `defaultSize` property.
Ensure the `defaultSize` totals to `100`.

> Note: The splitter only supports setting percentage values.

```jsx {3}
const service = useMachine(splitter.machine, {
  // ...
  defaultSize: [40, 60],
})
```

## Listening for resize events

When the resize trigger is dragged, the `onResize`, `onResizeStart` and
`onResizeEnd` callback is invoked.

```jsx {3-10}
const service = useMachine(splitter.machine, {
  // ...
  onResize(detail) {
    console.log("resize", detail)
  },
  onResizeStart(detail) {
    console.log("change start", detail)
  },
  onResizeEnd(detail) {
    console.log("change end", detail)
  },
})
```

## Changing the orientation

By default, the splitter is assumed to be horizontal. To change the orientation
to vertical, set the `orientation` property in the machine's context to
`vertical`.

```jsx {3}
const service = useMachine(splitter.machine, {
  // ...
  orientation: "vertical",
})
```

## Specifying constraints

Use the `panels` property to specify constraints like `minSize` and `maxSize`
for the splitter panels.

```jsx {3-6}
const service = useMachine(splitter.machine, {
  // ...
  panels: [
    { id: "a", minSize: 100, maxSize: 300 },
    { id: "b", minSize: 100, maxSize: 300 },
  ],
})
```

## Setting the collapsed size

Set the `collapsedSize` and `collapsible` of a panel to specify the collapsed
size of the panel.

> For best results, ensure you also set the `minSize` of the panel

```jsx {4}
const service = useMachine(splitter.machine, {
  // ...
  panels: [
    { id: "a", collapsible: true, collapsedSize: 5, minSize: 10, maxSize: 20 },
    { id: "b", minSize: 50 },
  ],
})
```

This allows the user to drag the splitter to collapse the panel to the
`collapsedSize`.

## Listening for collapse events

When the splitter panel is collapsed, the `onCollapse` callback is invoked.
Alternatively, the `onExpand` callback is invoked when the panel is expanded.

```jsx {3-8}
const service = useMachine(splitter.machine, {
  // ...
  onCollapse(detail) {
    console.log("collapse", detail)
  },
  onExpand(detail) {
    console.log("expand", detail)
  },
})
```

## Styling guide

Earlier, we mentioned that each accordion part has a `data-part` attribute added
to them to select and style them in the DOM.

### Resize trigger

When an splitter item is horizontal or vertical, a `data-state` attribute is set
on the item and content elements.

```css
[data-scope="splitter"][data-part="resize-trigger"] {
  /* styles for the item */
}

[data-scope="splitter"][data-part="resize-trigger"][data-orientation="horizontal"] {
  /* styles for the item is horizontal state */
}

[data-scope="splitter"][data-part="resize-trigger"][data-orientation="vertical"] {
  /* styles for the item is horizontal state */
}

[data-scope="splitter"][data-part="resize-trigger"][data-focus] {
  /* styles for the item is focus state */
}

[data-scope="splitter"][data-part="resize-trigger"]:active {
  /* styles for the item is active state */
}

[data-scope="splitter"][data-part="resize-trigger"][data-disabled] {
  /* styles for the item is disabled state */
}
```

## Methods and Properties

The splitter's `api` exposes the following methods and properties:

### Machine Context

The splitter machine exposes the following context properties:

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: The orientation of the splitter. Can be `horizontal` or `vertical`

**`size`**
Type: `number[]`
Description: The controlled size data of the panels

**`defaultSize`**
Type: `number[]`
Description: The initial size of the panels when rendered.
Use when you don't need to control the size of the panels.

**`panels`**
Type: `PanelData[]`
Description: The size constraints of the panels.

**`onResize`**
Type: `(details: ResizeDetails) => void`
Description: Function called when the splitter is resized.

**`onResizeStart`**
Type: `() => void`
Description: Function called when the splitter resize starts.

**`onResizeEnd`**
Type: `(details: ResizeEndDetails) => void`
Description: Function called when the splitter resize ends.

**`ids`**
Type: `Partial<{ root: string; resizeTrigger(id: string): string; label(id: string): string; panel(id: string | number): string; }>`
Description: The ids of the elements in the splitter. Useful for composition.

**`keyboardResizeBy`**
Type: `number`
Description: The number of pixels to resize the panel by when the keyboard is used.

**`nonce`**
Type: `string`
Description: The nonce for the injected splitter cursor stylesheet.

**`onCollapse`**
Type: `(details: ExpandCollapseDetails) => void`
Description: Function called when a panel is collapsed.

**`onExpand`**
Type: `(details: ExpandCollapseDetails) => void`
Description: Function called when a panel is expanded.

**`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 splitter `api` exposes the following methods:

**`dragging`**
Type: `boolean`
Description: Whether the splitter is currently being resized.

**`getSizes`**
Type: `() => number[]`
Description: The current sizes of the panels.

**`setSizes`**
Type: `(size: number[]) => void`
Description: Set the sizes of the panels.

**`getItems`**
Type: `() => SplitterItem[]`
Description: Get the items of the splitter.

**`getPanelSize`**
Type: `(id: string) => number`
Description: Get the size of a panel.

**`isPanelCollapsed`**
Type: `(id: string) => boolean`
Description: Whether a panel is collapsed.

**`isPanelExpanded`**
Type: `(id: string) => boolean`
Description: Whether a panel is expanded.

**`collapsePanel`**
Type: `(id: string) => void`
Description: Collapse a panel.

**`expandPanel`**
Type: `(id: string, minSize?: number) => void`
Description: Expand a panel.

**`resizePanel`**
Type: `(id: string, unsafePanelSize: number) => void`
Description: Resize a panel.

**`getLayout`**
Type: `() => string`
Description: Get the layout of the splitter.

### Data Attributes

**`Root`**

**`data-scope`**: splitter
**`data-part`**: root
**`data-orientation`**: The orientation of the splitter

**`Panel`**

**`data-scope`**: splitter
**`data-part`**: panel
**`data-orientation`**: The orientation of the panel
**`data-id`**: 
**`data-index`**: The index of the item

**`ResizeTrigger`**

**`data-scope`**: splitter
**`data-part`**: resize-trigger
**`data-id`**: 
**`data-orientation`**: The orientation of the resizetrigger
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled



# Steps

Steps are used to guide users through a series of steps in a process. It's a
great way to break down a complex process into smaller, more manageable steps.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/steps)
[Logic Visualizer](https://zag-visualizer.vercel.app/steps)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/steps)



**Features**

- Supports horizontal and vertical orientations.
- Support for changing the active step with the keyboard and pointer.
- Support for linear and non-linear steps.

## Installation

To use the steps machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/steps @zag-js/react
# or
yarn add @zag-js/steps @zag-js/react
```


This command will install the framework agnostic steps logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the steps 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

First, import the steps package into your project

```jsx
import * as steps from "@zag-js/steps"
```

The steps package exports two key functions:

- `machine` — The state machine logic for the steps widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
steps machine in your project 🔥

```jsx
import * as steps from "@zag-js/steps"
import { useMachine, normalizeProps } from "@zag-js/react"
import { useId } from "react"

const stepsData = [
  { title: "Step 1" },
  { title: "Step 2" },
  { title: "Step 3" },
]

function Steps() {
  const service = useMachine(steps.machine, {
    id: useId(),
    count: stepsData.length,
  })

  const api = steps.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getListProps()}>
        {stepsData.map((step, index) => (
          <div key={index} {...api.getItemProps({ index })}>
            <button {...api.getTriggerProps({ index })}>
              <div {...api.getIndicatorProps({ index })}>{index + 1}</div>
              <span>{step.title}</span>
            </button>
            <div {...api.getSeparatorProps({ index })} />
          </div>
        ))}
      </div>

      {stepsData.map((step, index) => (
        <div key={index} {...api.getContentProps({ index })}>
          {step.title}
        </div>
      ))}

      <div {...api.getContentProps({ index: stepsData.length })}>
        Steps Complete - Thank you for filling out the form!
      </div>

      <div>
        <button {...api.getPrevTriggerProps()}>Back</button>
        <button {...api.getNextTriggerProps()}>Next</button>
      </div>
    </div>
  )
}
```


## Setting the initial step

Set the initial step by passing the `step` property to the machine context.

> The value of the `step` property is zero-based index.

```jsx {2}
const service = useMachine(steps.machine, {
  defaultStep: 1,
})
```

## Listening for step change

When the active step changes, the machine will invoke the `onStepChange` event

```jsx {2-4}
const service = useMachine(steps.machine, {
  onStepChange(details) {
    // details => { step: number }
    console.log(`Step changed to ${details.step}`)
  },
})
```

## Listening for steps completion

When all steps are completed, the machine will invoke the `onStepComplete` event

```jsx {2-4}
const service = useMachine(steps.machine, {
  onStepComplete() {
    console.log("All steps are complete")
  },
})
```

## Enforcing linear steps

To enforce linear steps, you can set the `linear` prop to `true` when creating
the steps machine. This will prevent users from skipping steps.

```jsx {2}
const service = useMachine(steps.machine, {
  linear: true,
})
```

## Changing the orientation

The steps machine supports both horizontal and vertical orientations. You can
set the `orientation` prop to `horizontal` or `vertical` to change the
orientation of the steps.

```jsx {2}
const service = useMachine(steps.machine, {
  orientation: "vertical",
})
```

## Styling guide

Earlier, we mentioned that each steps part has a `data-part` attribute added to
them to select and style them in the DOM.

```css
[data-scope="steps"][data-part="root"] {
  /* styles for the root part */
}

[data-scope="steps"][data-part="root"][data-orientation="horizontal|vertical"] {
  /* styles for the root part based on orientation */
}

[data-scope="steps"][data-part="list"] {
  /* styles for the list part */
}

[data-scope="steps"][data-part="list"][data-orientation="horizontal|vertical"] {
  /* styles for the list part based on orientation */
}

[data-scope="steps"][data-part="separator"] {
  /* styles for the separator part */
}

[data-scope="steps"][data-part="separator"][data-orientation="horizontal|vertical"] {
  /* styles for the separator part based on orientation */
}
```

### Current step

To style the current step, you can use the `data-current` attribute.

```css
[data-scope="steps"][data-part="item"][data-current] {
  /* item styles for the current step */
}

[data-scope="steps"][data-part="separator"][data-current] {
  /* separator styles for the current step */
}
```

### Completed step

To style the completed step, you can use the `data-complete` attribute.

```css
[data-scope="steps"][data-part="item"][data-complete] {
  /* item styles for the completed step */
}

[data-scope="steps"][data-part="separator"][data-complete] {
  /* separator styles for the completed step */
}
```

### Incomplete step

To style the incomplete step, you can use the `data-incomplete` attribute.

```css
[data-scope="steps"][data-part="item"][data-incomplete] {
  /* item styles for the incomplete step */
}

[data-scope="steps"][data-part="separator"][data-incomplete] {
  /* separator styles for the incomplete step */
}
```

## Methods and Properties

### Machine Context

The steps machine exposes the following context properties:

**`ids`**
Type: `ElementIds`
Description: The custom ids for the stepper elements

**`step`**
Type: `number`
Description: The controlled value of the stepper

**`defaultStep`**
Type: `number`
Description: The initial value of the stepper when rendered.
Use when you don't need to control the value of the stepper.

**`onStepChange`**
Type: `(details: StepChangeDetails) => void`
Description: Callback to be called when the value changes

**`onStepComplete`**
Type: `VoidFunction`
Description: Callback to be called when a step is completed

**`linear`**
Type: `boolean`
Description: If `true`, the stepper requires the user to complete the steps in order

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: The orientation of the stepper

**`count`**
Type: `number`
Description: The total number of steps

**`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 steps `api` exposes the following methods:

**`value`**
Type: `number`
Description: The value of the stepper.

**`percent`**
Type: `number`
Description: The percentage of the stepper.

**`count`**
Type: `number`
Description: The total number of steps.

**`hasNextStep`**
Type: `boolean`
Description: Whether the stepper has a next step.

**`hasPrevStep`**
Type: `boolean`
Description: Whether the stepper has a previous step.

**`isCompleted`**
Type: `boolean`
Description: Whether the stepper is completed.

**`setStep`**
Type: `(step: number) => void`
Description: Function to set the value of the stepper.

**`goToNextStep`**
Type: `() => void`
Description: Function to go to the next step.

**`goToPrevStep`**
Type: `() => void`
Description: Function to go to the previous step.

**`resetStep`**
Type: `() => void`
Description: Function to go to reset the stepper.

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state of the item at the given index.

### Data Attributes

**`Root`**

**`data-scope`**: steps
**`data-part`**: root
**`data-orientation`**: The orientation of the steps

**`List`**

**`data-scope`**: steps
**`data-part`**: list
**`data-orientation`**: The orientation of the list

**`Item`**

**`data-scope`**: steps
**`data-part`**: item
**`data-orientation`**: The orientation of the item

**`Trigger`**

**`data-scope`**: steps
**`data-part`**: trigger
**`data-state`**: "open" | "closed"
**`data-orientation`**: The orientation of the trigger
**`data-complete`**: Present when the trigger value is complete
**`data-current`**: Present when current
**`data-incomplete`**: 

**`Content`**

**`data-scope`**: steps
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-orientation`**: The orientation of the content

**`Indicator`**

**`data-scope`**: steps
**`data-part`**: indicator
**`data-complete`**: Present when the indicator value is complete
**`data-current`**: Present when current
**`data-incomplete`**: 

**`Separator`**

**`data-scope`**: steps
**`data-part`**: separator
**`data-orientation`**: The orientation of the separator
**`data-complete`**: Present when the separator value is complete
**`data-current`**: Present when current
**`data-incomplete`**: 

**`Progress`**

**`data-scope`**: steps
**`data-part`**: progress
**`data-complete`**: Present when the progress value is complete



# Switch

A switch allows users to turn an individual option on or off.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/switch)
[Logic Visualizer](https://zag-visualizer.vercel.app/switch)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/switch)



**Features**

- Sync with `disabled` state of fieldset
- Sync with form `reset` events
- Can be toggled programmatically

## Installation

To use the switch machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/switch @zag-js/react
# or
yarn add @zag-js/switch @zag-js/react
```


This command will install the framework agnostic switch logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the switch 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

First, import the switch package into your project

```jsx
import * as zagSwitch from "@zag-js/switch"
```

The switch package exports two key functions:

- `machine` — The state machine logic for the switch widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
switch machine in your project 🔥

```jsx
import * as zagSwitch from "@zag-js/switch"
import { useMachine, normalizeProps } from "@zag-js/react"

function Checkbox() {
  const service = useMachine(zagSwitch.machine, { id: "1" })

  const api = zagSwitch.connect(service, normalizeProps)

  return (
    <label {...api.getRootProps()}>
      <input {...api.getHiddenInputProps()} />
      <span {...api.getControlProps()}>
        <span {...api.getThumbProps()} />
      </span>
      <span {...api.getLabelProps()}>{api.checked ? "On" : "Off"}</span>
    </label>
  )
}
```


## Disabling the switch

To make a switch disabled, set the context's `disabled` property to true

```jsx {3}
const service = useMachine(zagSwitch.machine, {
  disabled: true,
})
```

## Making it checked by default

To make a switch checked by default, set the context's `checked` property to
`true`

```jsx {3}
const service = useMachine(zagSwitch.machine, {
  defaultChecked: true,
})
```

## Listening for changes

When the switch value changes, the `onCheckedChange` callback is invoked.

```jsx {3-5}
const service = useMachine(zagSwitch.machine, {
  onCheckedChange(details) {
    // details => { checked: boolean }
    console.log("switch is:", details.checked ? "On" : "Off")
  },
})
```

## Usage within forms

To use switch within forms, use the exposed `inputProps` from the `connect`
function and ensure you pass `name` value to the machine's context. It will
render a hidden input and ensure the value changes get propagated to the form
correctly.

```jsx {3}
const service = useMachine(zagSwitch.machine, {
  name: "feature",
})
```

## Styling guide

Earlier, we mentioned that each switch part has a `data-part` attribute added to
them to select and style them in the DOM.

### Focused State

When the switch 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 switch 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 switch 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 switch machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; hiddenInput: string; control: string; label: string; thumb: string; }>`
Description: The ids of the elements in the switch. Useful for composition.

**`label`**
Type: `string`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`disabled`**
Type: `boolean`
Description: Whether the switch is disabled.

**`invalid`**
Type: `boolean`
Description: If `true`, the switch is marked as invalid.

**`required`**
Type: `boolean`
Description: If `true`, the switch input is marked as required,

**`readOnly`**
Type: `boolean`
Description: Whether the switch is read-only

**`onCheckedChange`**
Type: `(details: CheckedChangeDetails) => void`
Description: Function to call when the switch is clicked.

**`checked`**
Type: `boolean`
Description: The controlled checked state of the switch

**`defaultChecked`**
Type: `boolean`
Description: The initial checked state of the switch when rendered.
Use when you don't need to control the checked state of the switch.

**`name`**
Type: `string`
Description: The name of the input field in a switch
(Useful for form submission).

**`form`**
Type: `string`
Description: The id of the form that the switch belongs to

**`value`**
Type: `string | number`
Description: The value of switch 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 switch `api` exposes the following methods:

**`checked`**
Type: `boolean`
Description: Whether the checkbox is checked

**`disabled`**
Type: `boolean`
Description: Whether the checkbox is disabled

**`focused`**
Type: `boolean`
Description: Whether the checkbox is focused

**`setChecked`**
Type: `(checked: boolean) => void`
Description: Function to set the checked state of the switch.

**`toggleChecked`**
Type: `() => void`
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`**: "checked" | "unchecked"
**`data-invalid`**: Present when invalid

**`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`**: "checked" | "unchecked"
**`data-invalid`**: Present when invalid

**`Thumb`**

**`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`**: "checked" | "unchecked"
**`data-invalid`**: Present when invalid

**`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`**: "checked" | "unchecked"
**`data-invalid`**: Present when invalid

## Accessibility

Adheres to the
[Switch WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/switch/)

### Keyboard Interactions

**`Space + Enter`**
Description: Toggle the switch



# Tabs

An accessible tabs component that provides keyboard interactions and ARIA
attributes described in the WAI-ARIA Tabs Design Pattern. Tabs consist of a tab
list with one or more visually separated tabs. Each tab has associated content,
and only the selected tab's content is shown.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/tabs)
[Logic Visualizer](https://zag-visualizer.vercel.app/tabs)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tabs)



**Features**

- Support for mouse, touch, and keyboard interactions on tabs.
- Support for LTR and RTL keyboard navigation.
- Support for disabled tabs.
- Follows the tabs ARIA pattern, semantically linking tabs and their associated
  tab panels.
- Focus management for tab panels without any focusable children

## Installation

To use the tabs machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tabs @zag-js/react
# or
yarn add @zag-js/tabs @zag-js/react
```


This command will install the framework agnostic tabs logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the tabs 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

First, import the tabs package into your project

```jsx
import * as tabs from "@zag-js/tabs"
```

The tabs package exports two key functions:

- `machine` — The state machine logic for the tabs widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
tabs machine in your project 🔥

```jsx
import * as tabs from "@zag-js/tabs"
import { useMachine, normalizeProps } from "@zag-js/react"

const data = [
  { value: "item-1", label: "Item one", content: "Item one content" },
  { value: "item-2", label: "Item two", content: "Item two content" },
  { value: "item-3", label: "Item three", content: "Item three content" },
]

export function Tabs() {
  const service = useMachine(tabs.machine, { id: "1", defaultValue: "item-1" })

  const api = tabs.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getListProps()}>
        {data.map((item) => (
          <button
            {...api.getTriggerProps({ value: item.value })}
            key={item.value}
          >
            {item.label}
          </button>
        ))}
      </div>
      {data.map((item) => (
        <div {...api.getContentProps({ value: item.value })} key={item.value}>
          <p>{item.content}</p>
        </div>
      ))}
    </div>
  )
}
```


## Setting the selected tab

To set the initially selected tab, pass the `value` property to the machine's
context.

```jsx {2}
const service = useMachine(tabs.machine, {
  defaultValue: "tab-1",
})
```

Subsequently, you can use the `api.setValue` function to set the selected tab.

## Changing the orientation

The default orientation of the tabs is horizontal. To change the orientation,
set the `orientation` property in the machine's context to `"vertical"`.

```jsx {2}
const service = useMachine(tabs.machine, {
  orientation: "vertical",
})
```

## Showing an indicator

To show an active indicator when a tab is selected, you add the
`tabIndicatorProps` object provided by the `connect` function.

```jsx {13}
// ...
return (
  <div {...api.getRootProps()}>
    <div {...api.getListProps()}>
      {data.map((item) => (
        <button
          {...api.getTriggerProps({ value: item.value })}
          key={item.value}
        >
          {item.label}
        </button>
      ))}
      <div {...api.getIndicatorProps()} />
    </div>
    {data.map((item) => (
      <div {...api.getContentProps({ value: item.value })} key={item.value}>
        <p>{item.content}</p>
      </div>
    ))}
  </div>
)
```


## Disabling a tab

To disable a tab, set the `disabled` property in the `getTriggerProps` to
`true`.

When a Tab is `disabled`, it is skipped during keyboard navigation and it is not
clickable.

```jsx
//...
<button {...api.getTriggerProps({ disabled: true })}></button>
//...
```

## Listening for events

- `onValueChange` — Callback invoked when the selected tab changes.
- `onFocusChange` — Callback invoked when the focused tab changes.

```jsx {2-7}
const service = useMachine(tabs.machine, {
  onFocusChange(details) {
    // details => { value: string | null }
    console.log("focused tab:", details.value)
  },
  onValueChange(details) {
    // details => { value: string }
    console.log("selected tab:", details.value)
  },
})
```

## Manual tab activation

By default, the tab can be selected when the receive focus from either the
keyboard or pointer interaction. This is called "automatic tab activation".

The other approach is "manual tab activation" which means the tab is selected
with the Enter key or by clicking on the tab.

```jsx {2}
const service = useMachine(tabs.machine, {
  activationMode: "manual",
})
```

## RTL Support

The tabs machine provides support right to left writing directions. In this
mode, the layout and keyboard interaction is flipped.

To enable RTL support, set the `dir` property in the machine's context to `rtl`.

```jsx {2}
const service = useMachine(tabs.machine, {
  dir: "rtl",
})
```

## Styling guide

### Selected state

When a tab is selected, a `data-selected` attribute is added to the trigger and
content elements.

```css
[data-part="trigger"][data-state="active"] {
  /* Styles for selected tab */
}

[data-part="content"][data-state="active"] {
  /* Styles for selected tab */
}
```

### Disabled state

When a tab is disabled, a `data-disabled` attribute is added to the trigger
element.

```css
[data-part="trigger"][data-disabled] {
  /* Styles for disabled tab */
}
```

### Focused state

When a tab is focused, you the `:focus` or `:focus-visible` pseudo-class to
style it.

```css
[data-part="trigger"]:focus {
  /* Styles for focused tab */
}
```

When any tab is focused, the list is given a `data-focus` attribute.

```css
[data-part="list"][data-focus] {
  /* Styles for when any tab is focused */
}
```

### Orientation styles

All parts of the tabs component have the `data-orientation` attribute. You can
use this to set the style for the horizontal or vertical tabs.

```css
[data-part="trigger"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical tabs */
}

[data-part="root"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical root */
}

[data-part="indicator"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical tab-indicator */
}

[data-part="list"][data-orientation="(horizontal|vertical)"] {
  /* Styles for horizontal/vertical list */
}
```

### The tab indicator

The tab indicator styles have CSS variables for the `transitionDuration` and
`transitionTimingFunction` defined in it.

The transition definition is applied when the selected tab changes to allow the
indicator move smoothly to the new selected tab.

```css
[data-part="indicator"] {
  --transition-duration: 0.2s;
  --transition-timing-function: ease-in-out;
}
```

You'll also need to set the styles for the indicator to match your design.

```css
[data-part="indicator"] {
  --transition-duration: 0.2s;
  --transition-timing-function: ease-in-out;
}
```

## Methods and Properties

### Machine Context

The tabs machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; trigger: string; list: string; content: string; indicator: string; }>`
Description: The ids of the elements in the tabs. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`loopFocus`**
Type: `boolean`
Description: Whether the keyboard navigation will loop from last tab to first, and vice versa.

**`value`**
Type: `string`
Description: The controlled selected tab value

**`defaultValue`**
Type: `string`
Description: The initial selected tab value when rendered.
Use when you don't need to control the selected tab value.

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: The orientation of the tabs. Can be `horizontal` or `vertical`
- `horizontal`: only left and right arrow key navigation will work.
- `vertical`: only up and down arrow key navigation will work.

**`activationMode`**
Type: `"manual" | "automatic"`
Description: The activation mode of the tabs. Can be `manual` or `automatic`
- `manual`: Tabs are activated when clicked or press `enter` key.
- `automatic`: Tabs are activated when receiving focus

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Callback to be called when the selected/active tab changes

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Description: Callback to be called when the focused tab changes

**`composite`**
Type: `boolean`
Description: Whether the tab is composite

**`deselectable`**
Type: `boolean`
Description: Whether the active tab can be deselected when clicking on it.

**`navigate`**
Type: `(details: NavigateDetails) => void`
Description: Function to navigate to the selected tab when clicking on it.
Useful if tab triggers are anchor elements.

**`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 tabs `api` exposes the following methods:

**`value`**
Type: `string`
Description: The current value of the tabs.

**`focusedValue`**
Type: `string`
Description: The value of the tab that is currently focused.

**`setValue`**
Type: `(value: string) => void`
Description: Sets the value of the tabs.

**`clearValue`**
Type: `() => void`
Description: Clears the value of the tabs.

**`setIndicatorRect`**
Type: `(value: string) => void`
Description: Sets the indicator rect to the tab with the given value

**`syncTabIndex`**
Type: `() => void`
Description: Synchronizes the tab index of the content element.
Useful when rendering tabs within a select or combobox

**`focus`**
Type: `() => void`
Description: Set focus on the selected tab trigger

**`selectNext`**
Type: `(fromValue?: string) => void`
Description: Selects the next tab

**`selectPrev`**
Type: `(fromValue?: string) => void`
Description: Selects the previous tab

**`getTriggerState`**
Type: `(props: TriggerProps) => TriggerState`
Description: Returns the state of the trigger with the given props

### Data Attributes

**`Root`**

**`data-scope`**: tabs
**`data-part`**: root
**`data-orientation`**: The orientation of the tabs
**`data-focus`**: Present when focused

**`List`**

**`data-scope`**: tabs
**`data-part`**: list
**`data-focus`**: Present when focused
**`data-orientation`**: The orientation of the list

**`Trigger`**

**`data-scope`**: tabs
**`data-part`**: trigger
**`data-orientation`**: The orientation of the trigger
**`data-disabled`**: Present when disabled
**`data-value`**: The value of the item
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused
**`data-ssr`**: 

**`Content`**

**`data-scope`**: tabs
**`data-part`**: content
**`data-selected`**: Present when selected
**`data-orientation`**: The orientation of the content

**`Indicator`**

**`data-scope`**: tabs
**`data-part`**: indicator
**`data-orientation`**: The orientation of the indicator

## Accessibility

### Keyboard Interactions

**`Tab`**
Description: When focus moves onto the tabs, focuses the active trigger. When a trigger is focused, moves focus to the active content.

**`ArrowDown`**
Description: Moves focus to the next trigger in vertical orientation and activates its associated content.

**`ArrowRight`**
Description: Moves focus to the next trigger in horizontal orientation and activates its associated content.

**`ArrowUp`**
Description: Moves focus to the previous trigger in vertical orientation and activates its associated content.

**`ArrowLeft`**
Description: Moves focus to the previous trigger in horizontal orientation and activates its associated content.

**`Home`**
Description: Moves focus to the first trigger and activates its associated content.

**`End`**
Description: Moves focus to the last trigger and activates its associated content.

**`Enter + Space`**
Description: In manual mode, when a trigger is focused, moves focus to its associated content.



# Tags Input

Tag inputs render tags inside an input, followed by an actual text input. By
default, tags are added when text is typed in the input field and the `Enter` or
`Comma` key is pressed. Throughout the interaction, DOM focus remains on the
input element.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/tags-input)
[Logic Visualizer](https://zag-visualizer.vercel.app/tags-input)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tags-input)



**Features**

- Typing in the input and pressing enter will add new items.
- Clear button to reset all tags values.
- Add tags by pasting into the input.
- Delete tags on backspace.
- Edit tags after creation.
- Limit the number of tags.
- Navigate tags with keyboard.
- Custom validation to accept/reject tags.

## Installation

To use the tags input machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tags-input @zag-js/react
# or
yarn add @zag-js/tags-input @zag-js/react
```


## Anatomy

To set up the tags input 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

First, import the tags input package into your project

```jsx
import * as tagsInput from "@zag-js/tags-input"
```

The tags input package exports two key functions:

- `machine` — The state machine logic for the tags input widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> 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.

Next, import the required hooks and functions for your framework and use the
tags input machine in your project 🔥

```jsx
import * as tagsInput from "@zag-js/tags-input"
import { useMachine, normalizeProps } from "@zag-js/react"

export function TagsInput() {
  const service = useMachine(tagsInput.machine, {
    id: "1",
    value: ["React", "Vue"],
  })

  const api = tagsInput.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      {api.value.map((value, index) => (
        <span key={index} {...api.getItemProps({ index, value })}>
          <div {...api.getItemPreviewProps({ index, value })}>
            <span>{value} </span>
            <button {...api.getItemDeleteTriggerProps({ index, value })}>
              &#x2715;
            </button>
          </div>
          <input {...api.getItemInputProps({ index, value })} />
        </span>
      ))}
      <input placeholder="Add tag..." {...api.getInputProps()} />
    </div>
  )
}
```


## Navigating and Editing tags

When the input has an empty value or the caret is at the start position, the
tags can be selected by using the arrow left and arrow right keys. When "visual"
focus in on any tag:

- Pressing `Enter` or double clicking on the tag will put the it in edit mode,
  allowing the user change its value and press `Enter` to commit the changes.
- Pressing `Delete` or `Backspace` will delete the tag that has "visual" focus.

## Setting the initial tags

To set the initial tag values, pass the `value` property in the machine's
context.

```jsx {2}
const service = useMachine(tagsInput.machine, {
  defaultValue: ["React", "Redux", "TypeScript"],
})
```

## Removing all tags

The tags input will remove all tags when the clear button is clicked. To remove
all tags, use the provided `clearButtonProps` function from the `api`.

```jsx {4}
//...
<div {...api.getControlProps()}>
  <input {...api.getInputProps()} />
  <button {...api.getClearButtonProps()} />
</div>
//...
```

To programmatically remove all tags, use the `api.clearAll()` method that's
available in the `connect`.

## Usage within forms

The tags input works when placed within a form and the form is submitted. We
achieve this by:

- ensuring we emit the input event as the value changes.
- adding a `name` and `value` attribute to a hidden input so the tags can be
  accessed in the `FormData`.

To get this feature working you need to pass a `name` option to the context and
render the `hiddenInput` element.

```jsx {2}
const service = useMachine(tagsInput.machine, {
  name: "tags",
  defaultValue: ["React", "Redux", "TypeScript"],
})
```

## Limiting the number of tags

To limit the number of tags within the component, you can set the `max` property
to the limit you want. The default value is `Infinity`.

When the tag reaches the limit, new tags cannot be added except the
`allowOverflow` option is passed to the context.

```jsx {2-3}
const service = useMachine(tagsInput.machine, {
  max: 10,
  allowOverflow: true,
})
```

## Validating Tags

Before a tag is added, the machine provides a `validate` function you can use to
determine whether to accept or reject a tag.

A common use-case for validating tags is preventing duplicates or validating the
data type.

```jsx {2-3}
const service = useMachine(tagsInput.machine, {
  validate(details) {
    return !details.values.includes(details.inputValue)
  },
})
```

## Blur behavior

When the tags input is blurred, you can configure the action the machine should
take by passing the `blurBehavior` option to the context.

- `"add"` — Adds the tag to the list of tags.
- `"clear"` — Clears the tags input value.

```jsx {2}
const service = useMachine(tagsInput.machine, {
  blurBehavior: "add",
})
```

## Paste behavior

To add a tag when a arbitrary value is pasted in the input element, pass the
`addOnPaste` option.

When a value is pasted, the machine will:

- check if the value is a valid tag based on the `validate` option
- split the value by the `delimiter` option passed

```jsx {2}
const service = useMachine(tagsInput.machine, {
  addOnPaste: true,
})
```

## Disable tag editing

by default the tags can be edited by double clicking on the tag or focusing on
them and pressing `Enter`. To disable this behavior, pass the
`allowEditTag: false`

```jsx {2}
const service = useMachine(tagsInput.machine, {
  allowEditTag: false,
})
```

## Listening for events

During the lifetime of the tags input interaction, here's a list of events we
emit:

- `onValueChange` — invoked when the tag value changes.
- `onHighlightChange` — invoked when a tag has visual focus.
- `onValueInvalid` — invoked when the max tag count is reached or the `validate`
  function returns `false`.

```jsx
const service = useMachine(tagsInput.machine, {
  onValueChange(details) {
    // details => { value: string[] }
    console.log("tags changed to:", details.value)
  },
  onHighlightChange(details) {
    // details => { value: string }
    console.log("highlighted tag:", details.value)
  },
  onValueInvalid(details) {
    console.log("Invalid!", details.reason)
  },
})
```

## Styling guide

Earlier, we mentioned that each accordion part has a `data-part` attribute added
to them to select and style them in the DOM.

### Focused state

The combobox input is focused when the user clicks on the input element. In this
focused state, the root, label, input.

```css
[data-part="root"][data-focus] {
  /* styles for root focus state */
}

[data-part="label"][data-focus] {
  /* styles for label focus state */
}

[data-part="input"]:focus {
  /* styles for input focus state */
}
```

### Invalid state

When the tags input is invalid by setting the `invalid: true` in the machine's
context, the `data-invalid` attribute is set on the root, input, control, and
label.

```css
[data-part="root"][data-invalid] {
  /* styles for invalid state for root */
}

[data-part="label"][data-invalid] {
  /*  styles for invalid state for label */
}

[data-part="input"][data-invalid] {
  /*  styles for invalid state for input */
}
```

### Disabled state

When the tags input is disabled by setting the `disabled: true` in the machine's
context, the `data-disabled` attribute is set on the root, input, control and
label.

```css
[data-part="root"][data-disabled] {
  /* styles for disabled state for root */
}

[data-part="label"][data-disabled] {
  /* styles for disabled state for label */
}

[data-part="input"][data-disabled] {
  /* styles for disabled state for input */
}

[data-part="control"][data-disabled] {
  /* styles for disabled state for control */
}
```

When a tag is disabled, the `data-disabled` attribute is set on the tag.

```css
[data-part="item-preview"][data-disabled] {
  /* styles for disabled tag  */
}
```

### Highlighted state

When a tag is highlighted via the keyboard navigation or pointer hover, a
`data-highlighted` attribute is set on the tag.

```css
[data-part="item-preview"][data-highlighted] {
  /* styles for visual focus */
}
```

### Readonly state

When the tags input is in its readonly state, the `data-readonly` attribute is
set on the root, label, input and control.

```css
[data-part="root"][data-readonly] {
  /* styles for readonly for root */
}

[data-part="control"][data-readonly] {
  /* styles for readonly for control */
}

[data-part="input"][data-readonly] {
  /* styles for readonly for input  */
}

[data-part="label"][data-readonly] {
  /* styles for readonly for label */
}
```

## Methods and Properties

### Machine Context

The tags input machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; input: string; hiddenInput: string; clearBtn: string; label: string; control: string; item(opts: ItemProps): string; }>`
Description: The ids of the elements in the tags input. Useful for composition.

**`translations`**
Type: `IntlTranslations`
Description: Specifies the localized strings that identifies the accessibility elements and their states

**`maxLength`**
Type: `number`
Description: The max length of the input.

**`delimiter`**
Type: `string | RegExp`
Description: The character that serves has:
- event key to trigger the addition of a new tag
- character used to split tags when pasting into the input

**`autoFocus`**
Type: `boolean`
Description: Whether the input should be auto-focused

**`disabled`**
Type: `boolean`
Description: Whether the tags input should be disabled

**`readOnly`**
Type: `boolean`
Description: Whether the tags input should be read-only

**`invalid`**
Type: `boolean`
Description: Whether the tags input is invalid

**`required`**
Type: `boolean`
Description: Whether the tags input is required

**`editable`**
Type: `boolean`
Description: Whether a tag can be edited after creation, by pressing `Enter` or double clicking.

**`inputValue`**
Type: `string`
Description: The controlled tag input's value

**`defaultInputValue`**
Type: `string`
Description: The initial tag input value when rendered.
Use when you don't need to control the tag input value.

**`value`**
Type: `string[]`
Description: The controlled tag value

**`defaultValue`**
Type: `string[]`
Description: The initial tag value when rendered.
Use when you don't need to control the tag value.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Callback fired when the tag values is updated

**`onInputValueChange`**
Type: `(details: InputValueChangeDetails) => void`
Description: Callback fired when the input value is updated

**`onHighlightChange`**
Type: `(details: HighlightChangeDetails) => void`
Description: Callback fired when a tag is highlighted by pointer or keyboard navigation

**`onValueInvalid`**
Type: `(details: ValidityChangeDetails) => void`
Description: Callback fired when the max tag count is reached or the `validateTag` function returns `false`

**`validate`**
Type: `(details: ValidateArgs) => boolean`
Description: Returns a boolean that determines whether a tag can be added.
Useful for preventing duplicates or invalid tag values.

**`blurBehavior`**
Type: `"clear" | "add"`
Description: The behavior of the tags input when the input is blurred
- `"add"`: add the input value as a new tag
- `"clear"`: clear the input value

**`addOnPaste`**
Type: `boolean`
Description: Whether to add a tag when you paste values into the tag input

**`max`**
Type: `number`
Description: The max number of tags

**`allowOverflow`**
Type: `boolean`
Description: Whether to allow tags to exceed max. In this case,
we'll attach `data-invalid` to the root

**`name`**
Type: `string`
Description: The name attribute for the input. Useful for form submissions

**`form`**
Type: `string`
Description: The associate form of the underlying input element.

**`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 tags input `api` exposes the following methods:

**`empty`**
Type: `boolean`
Description: Whether the tags are empty

**`inputValue`**
Type: `string`
Description: The value of the tags entry input.

**`value`**
Type: `string[]`
Description: The value of the tags as an array of strings.

**`valueAsString`**
Type: `string`
Description: The value of the tags as a string.

**`count`**
Type: `number`
Description: The number of the tags.

**`atMax`**
Type: `boolean`
Description: Whether the tags have reached the max limit.

**`setValue`**
Type: `(value: string[]) => void`
Description: Function to set the value of the tags.

**`clearValue`**
Type: `(id?: string) => void`
Description: Function to clear the value of the tags.

**`addValue`**
Type: `(value: string) => void`
Description: Function to add a tag to the tags.

**`setValueAtIndex`**
Type: `(index: number, value: string) => void`
Description: Function to set the value of a tag at the given index.

**`setInputValue`**
Type: `(value: string) => void`
Description: Function to set the value of the tags entry input.

**`clearInputValue`**
Type: `() => void`
Description: Function to clear the value of the tags entry input.

**`focus`**
Type: `() => void`
Description: Function to focus the tags entry input.

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state of a tag

### Data Attributes

**`Root`**

**`data-scope`**: tags-input
**`data-part`**: root
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused
**`data-empty`**: 

**`Label`**

**`data-scope`**: tags-input
**`data-part`**: label
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`Control`**

**`data-scope`**: tags-input
**`data-part`**: control
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid
**`data-focus`**: Present when focused

**`Input`**

**`data-scope`**: tags-input
**`data-part`**: input
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`Item`**

**`data-scope`**: tags-input
**`data-part`**: item
**`data-value`**: The value of the item
**`data-disabled`**: Present when disabled

**`ItemPreview`**

**`data-scope`**: tags-input
**`data-part`**: item-preview
**`data-value`**: The value of the item
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted

**`ItemText`**

**`data-scope`**: tags-input
**`data-part`**: item-text
**`data-disabled`**: Present when disabled
**`data-highlighted`**: Present when highlighted

**`ClearTrigger`**

**`data-scope`**: tags-input
**`data-part`**: clear-trigger
**`data-readonly`**: Present when read-only

## Accessibility

### Keyboard Interactions

**`ArrowLeft`**
Description: Moves focus to the previous tag item

**`ArrowRight`**
Description: Moves focus to the next tag item

**`Backspace`**
Description: Deletes the tag item that has visual focus or the last tag item

**`Enter`**
Description: <span>When a tag item has visual focus, it puts the tag in edit mode.<br />When the input has focus, it adds the value to the list of tags</span>

**`Delete`**
Description: Deletes the tag item that has visual focus

**`Control + V`**
Description: When `addOnPaste` is set. Adds the pasted value as a tags



# Timer

The timer machine is used to record the time elapsed from zero or since a
specified target time.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/timer)
[Logic Visualizer](https://zag-visualizer.vercel.app/timer)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/timer)



**Features**

- Countdown from a specified time.
- Use as stopwatch to record the time elapsed.
- Control the timer with start, stop, and resume buttons.
- Set the tick interval for the timer.

## Installation

To use the Timer machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/timer @zag-js/react
# or
yarn add @zag-js/timer @zag-js/react
```


## Anatomy

To set up the Timer 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

First, import the timer package into your project

```jsx
import * as timer from "@zag-js/timer"
```

The Timer package exports these functions:

- `machine` — The state machine logic for the Time Picker widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.
- `parse` — The function to parse a date time string or object into a `Time`
  object.

> 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.

Next, import the required hooks and functions for your framework and use the
Time Picker machine in your project 🔥

```jsx
import { normalizeProps, useMachine } from "@zag-js/react"
import * as timer from "@zag-js/timer"

export function Countdown() {
  const service = useMachine(timer.machine, {
    id: useId(),
    countdown: true,
    autoStart: true,
    startMs: timer.parse({ days: 2, seconds: 10 }),
  })

  const api = timer.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <div {...api.getAreaProps()}>
        <div {...api.getItemProps({ type: "days" })}>
          {api.formattedTime.days}
        </div>
        <div {...api.getSeparatorProps()}>:</div>
        <div {...api.getItemProps({ type: "hours" })}>
          {api.formattedTime.hours}
        </div>
        <div {...api.getSeparatorProps()}>:</div>
        <div {...api.getItemProps({ type: "minutes" })}>
          {api.formattedTime.minutes}
        </div>
        <div {...api.getSeparatorProps()}>:</div>
        <div {...api.getItemProps({ type: "seconds" })}>
          {api.formattedTime.seconds}
        </div>
      </div>
      <div {...api.getControlProps()}>
        <button {...api.getActionTriggerProps({ action: "start" })}>
          START
        </button>
        <button {...api.getActionTriggerProps({ action: "pause" })}>
          PAUSE
        </button>
        <button {...api.getActionTriggerProps({ action: "resume" })}>
          RESUME
        </button>
        <button {...api.getActionTriggerProps({ action: "reset" })}>
          RESET
        </button>
      </div>
    </div>
  )
}
```


## Setting the start value

Set the `startMs` property to the timer machine's context to set the start time
in milliseconds.

```jsx
const service = useMachine(timer.machine, {
  startMs: 1000 * 60 * 60, // 1 hour
})
```

Alternatively, you can also use the `timer.parse` function to convert a date
time string or object into milliseconds

```jsx
const service = useMachine(timer.machine, {
  startMs: timer.parse("2021-01-01T12:00:00Z"),
  // startMs: timer.parse({ hours: 12, minutes: 0, seconds: 0 }),
})
```

## Auto starting the timer

Set the `autoStart` property to `true` in the timer machine's context to start
the timer automatically when the component mounts.

```jsx
const service = useMachine(timer.machine, {
  autoStart: true,
})
```

## Usage as countdown timer

To use the timer as a countdown timer, set the `countdown` property to `true` in
the timer machine's context.

```jsx
const service = useMachine(timer.machine, {
  countdown: true,
})
```

## Setting the target value

To set the target value of the countdown timer, pass the `targetMs` property in
the timer machine's context. The timer stops automatically when the `targetMs`
is reached.

When `targetMs` is set and `countdown=true`, the timer ticks down to zero from
the specified target time.

```jsx
const service = useMachine(timer.machine, {
  countdown: true,
  targetMs: 1000 * 60 * 60, // 1 hour
})
```

When `targetMs` is set and `countdown=false|undefined`, the timer ticks up to
the specified target time.

```jsx
const service = useMachine(timer.machine, {
  targetMs: 1000 * 60 * 60, // 1 hour
})
```

## Setting the tick interval

Set the `interval` property to the timer machine's context to set the tick
interval in milliseconds.

```jsx
const service = useMachine(timer.machine, {
  interval: 1000, // 1 second
})
```

## Listening to tick events

When the timer ticks, the `onTick` callback is invoke. You can listen to this
event and update your UI accordingly.

```jsx
const service = useMachine(timer.machine, {
  onTick(details) {
    // details => { value, segments }
    console.log(details)
  },
})
```

## Listening for completion events

When the timer reaches the target time, the `onComplete` callback is invoked.

```jsx
const service = useMachine(timer.machine, {
  countdown: true,
  targetMs: 1000 * 60 * 60, // 1 hour
  onComplete() {
    console.log("Timer completed")
  },
})
```

## Starting and Stopping the timer

To start the timer, send the `api.start()` callback

```jsx
api.start()
```

To stop the timer, send the `api.stop()` callback

```jsx
api.stop()
```

## Pausing and Resuming the timer

To pause the timer, send the `api.pause()` callback

```jsx
api.pause()
```

To resume the timer, send the `api.resume()` callback

```jsx
api.resume()
```

## Methods and Properties

### Machine Context

The time picker machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; area: string; }>`
Description: The ids of the timer parts

**`countdown`**
Type: `boolean`
Description: Whether the timer should countdown, decrementing the timer on each tick.

**`startMs`**
Type: `number`
Description: The total duration of the timer in milliseconds.

**`targetMs`**
Type: `number`
Description: The minimum count of the timer in milliseconds.

**`autoStart`**
Type: `boolean`
Description: Whether the timer should start automatically

**`interval`**
Type: `number`
Description: The interval in milliseconds to update the timer count.

**`onTick`**
Type: `(details: TickDetails) => void`
Description: Function invoked when the timer ticks

**`onComplete`**
Type: `() => void`
Description: Function invoked when the timer is completed

**`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 time picker `api` exposes the following methods:

**`running`**
Type: `boolean`
Description: Whether the timer is running.

**`paused`**
Type: `boolean`
Description: Whether the timer is paused.

**`time`**
Type: `Time<number>`
Description: The formatted timer count value.

**`formattedTime`**
Type: `Time<string>`
Description: The formatted time parts of the timer count.

**`start`**
Type: `() => void`
Description: Function to start the timer.

**`pause`**
Type: `() => void`
Description: Function to pause the timer.

**`resume`**
Type: `() => void`
Description: Function to resume the timer.

**`reset`**
Type: `() => void`
Description: Function to reset the timer.

**`restart`**
Type: `() => void`
Description: Function to restart the timer.

**`progressPercent`**
Type: `number`
Description: The progress percentage of the timer.



# Toast

The toast component is used to give feedback to users after an action has taken
place.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/toast)
[Logic Visualizer](https://zag-visualizer.vercel.app/toast)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/toast)



**Features**

- Support for screen readers.
- Limit the number of visible toasts.
- Manage promises within toast.
- Pause on hover, focus or page idle.
- Can remove or update toast programmatically.

## Installation

To use the toast machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/toast @zag-js/react
# or
yarn add @zag-js/toast @zag-js/react
```


This command will install the framework agnostic toast logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the toast 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

First, import the toast package into your project

```jsx
import * as toast from "@zag-js/toast"
```

Next, import the required hooks and functions for your framework and use the
toast machine in your project 🔥

```jsx
import { useMachine, normalizeProps } from "@zag-js/react"
import * as toast from "@zag-js/toast"
import { useId } from "react"

// 1. Create the toast store
const toaster = toast.createStore({
  overlap: true,
  placement: "top-end",
})

// 2. Design the toast component
function Toast(props) {
  const machineProps = {
    ...props.toast,
    parent: props.parent,
    index: props.index,
  }
  const service = useMachine(toast.machine, machineProps)
  const api = toast.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <h3 {...api.getTitleProps()}>{api.title}</h3>
      <p {...api.getDescriptionProps()}>{api.description}</p>
      <button onClick={api.dismiss}>Close</button>
    </div>
  )
}

// 3. Design the toaster
export function Toaster() {
  const service = useMachine(toast.group.machine, {
    id: useId(),
    store: toaster,
  })
  const api = toast.group.connect(service, normalizeProps)
  return (
    <div {...api.getGroupProps()}>
      {api.getToasts().map((toast, index) => (
        <Toast key={toast.id} toast={toast} parent={service} index={index} />
      ))}
    </div>
  )
}

// 4. Render the toaster in your app
export function App() {
  return (
    <>
      <Toaster />
      <ExampleComponent />
    </>
  )
}

// 5. Within your app
function Demo() {
  return (
    <div>
      <button
        onClick={() => {
          toaster.create({ title: "Hello" })
        }}
      >
        Info toast
      </button>
      <button
        onClick={() => {
          toaster.create({ title: "Data submitted!", type: "success" })
        }}
      >
        Success toast
      </button>
    </div>
  )
}
```


The use the toast effectively, you need to understand these key aspects:

### Toast Group

- `toast.group.machine` — The state machine representation of a group of toasts.
  It is responsible for spawning, updating and removing toasts.
- `toast.group.connect` — function gives you access to methods you can use to
  add, update, and remove a toast.

  > We recommend setting up the toast group machine once at the root of your
  > project.

### Toast Item

- `toast.machine` — The state machine representation of a single toast.
- `toast.connect` — The function that takes the toast machine and returns
  methods and JSX properties.

## Creating a toast

There are five toast types that can be created with the toast machine. `info`,
`success`, `loading`, `custom` and `error`.

To create a toast, use the `toaster.create(...)` method.

```jsx
toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
})
```

The options you can pass in are:

- `title` — The title of the toast.
- `description` — The description of the toast.
- `type` — The type of the toast. Can be either `error`, `success` , `info`,
  `loading`, or `custom`.
- `duration` — The duration of the toast. The default duration is computed based
  on the specified `type`.
- `onStatusChange` — A callback that listens for the status changes across the
  toast lifecycle.
- `removeDelay` — The delay before unmounting the toast from the DOM. Useful for
  transition.

## Changing the placement

Use the `placement` property when you call the `toaster.create(...)` to change
the position of the toast.

```jsx {4}
toaster.info({
  title: "Hello World",
  description: "This is a toast",
  placement: "top-start",
})
```

## Overlapping toasts

When multiple toasts are created, they are rendered in a stack. To make the
toasts overlap, set the `overlap` property to `true`.

```jsx
const toaster = toast.createStore({
  overlap: true,
})
```

When using overlap, the toast's placement must match the `placement` of the
toast group (which is `bottom` by default).

> Be sure to set up the [required styles](#requirement) to make the toasts
> overlap correctly.

## Changing the duration

Every toast has a default visible duration depending on the `type` set. Here's
the following toast types and matching default durations:

<PropValueTable
  items={{
    headings: ["type", "duration"],
    data: [
      ["info", "5000"],
      ["error", "5000"],
      ["success", "2000"],
      ["loading", "Infinity"],
    ],
  }}
/>

You can override the duration of the toast by passing the `duration` property to
the `toaster.create(...)` function.

```jsx {5}
toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  duration: 6000,
})
```

> You can also use the `toaster.upsert(...)` function which creates or updates a
> toast.

## Using portals

Using a portal is helpful to ensure that the toast is rendered outside the DOM
hierarchy of the parent component. To render the toast in a portal, wrap the
rendered toasts in the `ToastProvider` within your framework-specific portal.

```jsx {1,12,16}
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import * as toast from "@zag-js/toast"

// ...

// 3. Create the toast group provider, wrap your app with it
export function Toaster() {
  const service = useMachine(toast.group.machine, { id: "1", store: toaster })
  const api = toast.group.connect(service, normalizeProps)

  return (
    <Portal>
      {api.getToasts().map((toast, index) => (
        <Toast key={toast.id} actor={toast} parent={service} index={index} />
      ))}
    </Portal>
  )
}
```


## Programmatic control

To update a toast programmatically, you need access to the unique identifier of
the toast.

This identifier can be either:

- the `id` passed into `toaster.create(...)` or,
- the returned random `id` when the `toaster.create(...)` is called.

You can use any of the following methods to control a toast:

- `toaster.upsert(...)` — Creates or updates a toast.
- `toaster.update(...)` — Updates a toast.
- `toaster.remove(...)` — Removes a toast instantly without delay.
- `toaster.dismiss(...)` — Removes a toast with delay.
- `toaster.pause(...)` — Pauses a toast.
- `toaster.resume(...)` — Resumes a toast.

```jsx {2,11-15}
// grab the id from the created toast
const id = toaster.create({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  duration: 6000,
  placement: "top-start",
})

// update the toast
toaster.update(id, {
  title: "Hello World",
  description: "This is a toast",
  type: "success",
})

// remove the toast
toaster.remove(id)

// dismiss the toast
toaster.dismiss(id)
```

## Handling promises

The toast group API exposes a `toaster.promise()` function to allow you update
the toast when it resolves or rejects.

> With the promise API, you can pass the toast options for each promise
> lifecycle.

```jsx
toaster.promise(promise, {
  loading: {
    title: "Loading",
    description: "Please wait...",
  },
  success: (data) => ({
    title: "Success",
    description: "Your request has been completed",
  }),
  error: (err) => ({
    title: "Error",
    description: "An error has occurred",
  }),
})
```

## Pausing the toasts

There are three scenarios we provide to pause a toast from timing out:

- When the document loses focus or the page is idle (e.g. switching to a new
  browser tab), controlled via the `pauseOnPageIdle` context property.
- When the `toaster.pause(id)` is called.

```jsx
// Global pause options
const service = useMachine(toast.group.machine, {
  pauseOnPageIdle: true,
})

// Programmatically pause a toast (by `id`)
// `id` is the return value of `api.create(...)`
toaster.pause(id)
```

## Limiting the number of toasts

Toasts are great but displaying too many of them can sometimes hamper the user
experience. To limit the number of visible toasts, pass the `max` property to
the group machine's context.

```jsx {3}
const toaster = toast.createStore({
  max: 10,
})
```

## Focus Hotkey for toasts

When a toast is created, you can focus the toast region by pressing the
`alt + T`. This is useful for screen readers and keyboard navigation.

Set the `hotkey` context property to change the underlying hotkey.

```jsx
const service = useMachine(toast.group.machine, {
  hotkey: ["F6"],
})
```

## Listening for toast lifecycle

When a toast is created, you can listen for the status changes across its
lifecycle using the `onStatusChange` callback when you call
`toaster.create(...)`.

The status values are:

- `visible` - The toast is mounted and rendered
- `dismissed` - The toast is visually invisible but still mounted
- `unmounted` - The toast has been completely unmounted and no longer exists

```jsx {3-7}
toaster.info({
  title: "Hello World",
  description: "This is a toast",
  type: "info",
  onStatusChange: (details) => {
    // details => { status: "visible" | "dismissed" | "unmounted" }
    console.log("Toast status:", details)
  },
})
```

## Changing the gap between toasts

When multiple toasts are rendered, a gap of `16px` is applied between each
toast. To change this value, set the `gap` context property.

```jsx {3}
const service = useMachine(toast.group.machine, {
  gap: 24,
})
```

## Changing the offset

The toast region has a default `16px` offset from the viewport. Use the `offset`
context property to change the offset.

```jsx {4-8}
const service = useMachine(toast.group.machine, {
  offsets: "24px",
})
```

## Styling guide

### Requirement

The toast machine injects a bunch of css variables that are required for it to
work. You need to connect these variables in your styles.

```css
[data-part="root"] {
  translate: var(--x) var(--y);
  scale: var(--scale);
  z-index: var(--z-index);
  height: var(--height);
  opacity: var(--opacity);
  will-change: translate, opacity, scale;
}
```

To make it transition smoothly, you should includes `transition` properties.

```css
[data-part="root"] {
  transition:
    translate 400ms,
    scale 400ms,
    opacity 400ms;
  transition-timing-function: cubic-bezier(0.21, 1.02, 0.73, 1);
}

[data-part="root"][data-state="closed"] {
  transition:
    translate 400ms,
    scale 400ms,
    opacity 200ms;
  transition-timing-function: cubic-bezier(0.06, 0.71, 0.55, 1);
}
```

### Toast styling

When a toast is created and the `api.getRootProps()` from the `toast.connect` is
used, the toast will have a `data-type` that matches the specified `type` at its
creation.

You can use this property to style the toast.

```css
[data-part="root"][data-type="info"] {
  /* Styles for the specific toast type */
}

[data-part="root"][data-type="error"] {
  /* Styles for the error toast type */
}

[data-part="root"][data-type="success"] {
  /* Styles for the success toast type */
}

[data-part="root"][data-type="loading"] {
  /* Styles for the loading toast type */
}
```

## Methods and Properties

### Machine API

The toast's `api` exposes the following methods:

**`getCount`**
Type: `() => number`
Description: The total number of toasts

**`getToasts`**
Type: `() => ToastProps<any>[]`
Description: The toasts

**`subscribe`**
Type: `(callback: (toasts: Options<O>[]) => void) => VoidFunction`
Description: Subscribe to the toast group

### Data Attributes

**`Root`**

**`data-scope`**: toast
**`data-part`**: root
**`data-state`**: "open" | "closed"
**`data-type`**: The type of the item
**`data-placement`**: The placement of the toast
**`data-align`**: 
**`data-side`**: 
**`data-mounted`**: Present when mounted
**`data-paused`**: Present when paused
**`data-first`**: 
**`data-sibling`**: 
**`data-stack`**: 
**`data-overlap`**: Present when overlapping

**`GhostBefore`**

**`data-scope`**: toast
**`data-part`**: ghost-before
**`data-ghost`**: 

**`GhostAfter`**

**`data-scope`**: toast
**`data-part`**: ghost-after
**`data-ghost`**: 



# Toggle Group

A toggle group is used to toggle either one option or multiple options.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/toggle-group)
[Logic Visualizer](https://zag-visualizer.vercel.app/toggle-group)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/toggle-group)



**Features**

- Fully managed keyboard navigation.
- Supports horizontal and vertical orientation.
- Support for multiple selection.

## Installation

To use the toggle group machine in your project, run the following command in
your command line:

```bash
npm install @zag-js/toggle-group @zag-js/react
# or
yarn add @zag-js/toggle-group @zag-js/react
```


This command will install the framework agnostic toggle group logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the toggle group 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

First, import the toggle group package into your project

```jsx
import * as toggle from "@zag-js/toggle-group"
```

The toggle group package exports two key functions:

- `machine` — The state machine logic for the toggle group widget as described
  in the WAI-ARIA spec.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

> You'll need to provide a unique `id` to the `useMachine` hook. This is used to
> ensure that every part has a unique identifier.

Next, import the required hooks and functions for your framework and use the
toggle group machine in your project 🔥

```jsx
import { normalizeProps, useMachine } from "@zag-js/react"
import * as toggle from "@zag-js/toggle-group"
import { useId } from "react"

export function ToggleGroup() {
  const service = useMachine(toggle.machine, { id: useId() })
  const api = toggle.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <button {...api.getItemProps({ value: "bold" })}>B</button>
      <button {...api.getItemProps({ value: "italic" })}>I</button>
      <button {...api.getItemProps({ value: "underline" })}>U</button>
    </div>
  )
}
```


## Changing the orientation

By default, the toggle group is assumed to be horizontal. To change the
orientation to vertical, set the `orientation` property in the machine's context
to `vertical`.

```jsx {2}
const service = useMachine(toggle.machine, {
  orientation: "vertical",
})
```

## Listening for value changes

When the pressed toggle in the group changes, `onValueChange` callback is
invoked.

```jsx {2-4}
const service = useMachine(toggle.machine, {
  onValueChange(details) {
    // details => { value: string[] }
    console.log(details.value)
  },
})
```

## Allowing multiple selection

Set the `multiple` property in the machine's context to `true` to allow multiple
options to be toggled.

```jsx {2}
const service = useMachine(toggle.machine, {
  multiple: true,
})
```

## Disabling the toggle group

Set the `disabled` property in the machine's context to `true` to disable the
toggle group.

```jsx {2}
const service = useMachine(toggle.machine, {
  disabled: true,
})
```

## Disabling a toggle

Set the `disabled` property in the `getToggleProps` function to `true` to
disable a toggle.

```jsx
//...
<div {...api.getRootProps()}>
  <button {...api.getToggleProps({ value: "bold", disabled: true })}>B</button>
</div>
//...
```

## Disabling focus loop

The toggle group loops keyboard navigation by default. To disable this, set the
`loop` property in the machine's context to `false`.

```jsx {2}
const service = useMachine(toggle.machine, {
  loop: false,
})
```

## Disabling roving focus management

The toggle group uses roving focus management by default. To disable this, set
the `rovingFocus` property in the machine's context to `false`.

```jsx {2}
const service = useMachine(toggle.machine, {
  rovingFocus: false,
})
```

## Styling Guide

Earlier, we mentioned that each toggle group part has a `data-part` attribute
added to them to select and style them in the DOM.

### Pressed State

The toggle is pressed, the `data-state` attribute is applied to the toggle
button with `on` or `off` values.

```css
[data-part="toggle"][data-state="on|off"] {
  /* styles for toggle button */
}
```

### Focused State

When a toggle button is focused, the `data-focus` is applied to the root and
matching toggle button.

```css
[data-part="root"][data-focus] {
  /* styles for the root */
}

[data-part="toggle"][data-focus] {
  /* styles for the toggle */
}
```

### Disabled State

When a toggle button is disabled, the `data-disabled` is applied to the root and
matching toggle button.

```css
[data-part="root"][data-disabled] {
  /* styles for the root */
}

[data-part="toggle"][data-disabled] {
  /* styles for the toggle */
}
```

## Methods and Properties

### Machine Context

The toggle group machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; item(value: string): string; }>`
Description: The ids of the elements in the toggle. Useful for composition.

**`disabled`**
Type: `boolean`
Description: Whether the toggle is disabled.

**`value`**
Type: `string[]`
Description: The controlled selected value of the toggle group.

**`defaultValue`**
Type: `string[]`
Description: The initial selected value of the toggle group when rendered.
Use when you don't need to control the selected value of the toggle group.

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Function to call when the toggle is clicked.

**`loopFocus`**
Type: `boolean`
Description: Whether to loop focus inside the toggle group.

**`rovingFocus`**
Type: `boolean`
Description: Whether to use roving tab index to manage focus.

**`orientation`**
Type: `Orientation`
Description: The orientation of the toggle group.

**`multiple`**
Type: `boolean`
Description: Whether to allow multiple toggles to be selected.

**`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 toggle group `api` exposes the following methods:

**`value`**
Type: `string[]`
Description: The value of the toggle group.

**`setValue`**
Type: `(values: string[]) => void`
Description: Function to set the value of the toggle group.

**`getItemState`**
Type: `(props: ItemProps) => ItemState`
Description: Returns the state of the toggle item.

### Data Attributes

**`Root`**

**`data-scope`**: toggle-group
**`data-part`**: root
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the toggle-group
**`data-focus`**: Present when focused

**`Item`**

**`data-scope`**: toggle-group
**`data-part`**: item
**`data-focus`**: Present when focused
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the item
**`data-state`**: "on" | "off"

## Accessibility

Uses
[roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/radio/radio.html)
to manage focus movement among items.

### Keyboard Interactions

**`Tab`**
Description: Moves focus to either the pressed item or the first item in the group.

**`Space`**
Description: Activates/deactivates the item.

**`Enter`**
Description: Activates/deactivates the item.

**`ArrowDown`**
Description: Moves focus to the next item in the group.

**`ArrowRight`**
Description: Moves focus to the next item in the group.

**`ArrowUp`**
Description: Moves focus to the previous item in the group.

**`ArrowLeft`**
Description: Moves focus to the previous item in the group.

**`Home`**
Description: Moves focus to the first item.

**`End`**
Description: Moves focus to the last item.



# Tooltip

A tooltip is a brief, informative message that appears when a user interacts
with an element. Tooltips are usually initiated when a button is focused or
hovered.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/tooltip)
[Logic Visualizer](https://zag-visualizer.vercel.app/tooltip)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tooltip)



**Features**

- Show tooltip on hover and focus.
- Hide tooltip on esc or pointer down.
- Only one tooltip shows at a time.
- Labeling support for screen readers via `aria-describedby`.
- Custom show and hide delay support.
- Matches native tooltip behavior with delay on hover of first tooltip and no
  delay on subsequent tooltips.

## Installation

To use the tooltip machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tooltip @zag-js/react
# or
yarn add @zag-js/tooltip @zag-js/react
```


This command will install the framework agnostic tooltip logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the tooltip 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

First, import the tooltip package into your project

```jsx
import * as tooltip from "@zag-js/tooltip"
```

The tooltip package exports two key functions:

- `machine` — The state machine logic for the tooltip widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

To get the tooltip working correct, you'll need to:

- Setup the tooltip portal, this is a shared container for all tooltips
- Add the `triggerProps`, and `tooltipProps` to the elements

> 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.

Next, import the required hooks and functions for your framework and use the
tooltip machine in your project 🔥

```jsx
import * as tooltip from "@zag-js/tooltip"
import { useMachine, normalizeProps } from "@zag-js/react"

export function Tooltip() {
  const service = useMachine(tooltip.machine, { id: "1" })

  const api = tooltip.connect(service, normalizeProps)

  return (
    <>
      <button {...api.getTriggerProps()}>Hover me</button>
      {api.open && (
        <div {...api.getPositionerProps()}>
          <div {...api.getContentProps()}>Tooltip</div>
        </div>
      )}
    </>
  )
}
```


## Customizing the timings

By default, the tooltip is designed to open after `1000ms` and close after
`500ms`. You can customize this by passing the `openDelay` and `closeDelay`
context properties.

```jsx {2-3}
const service = useMachine(tooltip.machine, {
  openDelay: 500,
  closeDelay: 200,
})
```

## Changing the placement

The tooltip uses [floating-ui](https://floating-ui.com/) for dynamic
positioning. You can change the placement of the tooltip by passing the
`positioning.placement` context property to the machine.

```jsx {2-4}
const service = useMachine(tooltip.machine, {
  positioning: {
    placement: "bottom-start",
  },
})
```

You can configure other position-related properties in the `positioning` object.
Here's what the positioning API looks like:

```ts
export type PositioningOptions = {
  /**
   * The strategy to use for positioning
   */
  strategy?: "absolute" | "fixed"
  /**
   * The initial placement of the floating element
   */
  placement?: Placement
  /**
   * The offset of the floating element
   */
  offset?: { mainAxis?: number; crossAxis?: number }
  /**
   * The main axis offset or gap between the reference and floating elements
   */
  gutter?: number
  /**
   * Whether to flip the placement
   */
  flip?: boolean
  /**
   * Whether to make the floating element same width as the reference element
   */
  sameWidth?: boolean
  /**
   * The overflow boundary of the reference element
   */
  boundary?: Boundary
  /**
   * Options to activate auto-update listeners
   */
  listeners?: boolean | AutoUpdateOptions
}
```

## Adding an arrow

To render an arrow within the tooltip, use the `api.getArrowProps()` and
`api.getArrowTipProps()`.

```jsx {6-8}
//...
const api = popover.connect(service, normalizeProps)
//...
return (
  <div {...api.getPositionerProps()}>
    <div {...api.getArrowProps()}>
      <div {...api.getArrowTipProps()} />
    </div>
    <div {...api.getContentProps()}>{/* ... */}</div>
  </div>
)
//...
```

## Pointerdown behavior

By default, the tooltip will close when the pointer is down on its trigger. To
prevent this behavior, pass the `closeOnPointerDown` context property and set it
to `false`.

```jsx {2}
const service = useMachine(tooltip.machine, {
  closeOnPointerDown: false,
})
```

## Closing on Esc

The tooltip is designed to close when the escape key is pressed. To prevent
this, pass the `closeOnEscape` context property and set it to `false`.

```jsx {2}
const service = useMachine(tooltip.machine, {
  closeOnEsc: false,
})
```

## Making the tooltip interactive

Set the `interactive` context property to `true` to make them interactive.

When a tooltip is interactive, it'll remain open even the pointer leaves the
trigger and move into the tooltip's content.

```jsx {2}
const service = useMachine(tooltip.machine, {
  interactive: true,
})
```

## Listening for open state changes

When the tooltip is opened or closed, the `onOpenChange` callback is invoked.

```jsx {2-7}
const service = useMachine(tooltip.machine, {
  onOpenChange(details) {
    // details => { open: boolean }
    console.log(details.open)
  },
})
```

## Styling guide

Earlier, we mentioned that each tooltip part has a `data-part` attribute added
to them to select and style them in the DOM.

```css
[data-part="trigger"] {
  /* styles for the content */
}

[data-part="content"] {
  /* styles for the content */
}
```

### Open and close states

When the tooltip is open, the `data-state` attribute is added to the trigger

```css
[data-part="trigger"][data-state="open|closed"] {
  /* styles for the trigger's expanded state */
}

[data-part="content"][data-state="open|closed"] {
  /* styles for the trigger's expanded state */
}
```

### Styling the arrow

When using arrows within the menu, you can style it using css variables.

```css
[data-part="arrow"] {
  --arrow-size: 20px;
  --arrow-background: red;
}
```

## Methods and Properties

### Machine Context

The tooltip machine exposes the following context properties:

**`ids`**
Type: `Partial<{ trigger: string; content: string; arrow: string; positioner: string; }>`
Description: The ids of the elements in the tooltip. Useful for composition.

**`openDelay`**
Type: `number`
Description: The open delay of the tooltip.

**`closeDelay`**
Type: `number`
Description: The close delay of the tooltip.

**`closeOnPointerDown`**
Type: `boolean`
Description: Whether to close the tooltip on pointerdown.

**`closeOnEscape`**
Type: `boolean`
Description: Whether to close the tooltip when the Escape key is pressed.

**`closeOnScroll`**
Type: `boolean`
Description: Whether the tooltip should close on scroll

**`closeOnClick`**
Type: `boolean`
Description: Whether the tooltip should close on click

**`interactive`**
Type: `boolean`
Description: Whether the tooltip's content is interactive.
In this mode, the tooltip will remain open when user hovers over the content.

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Function called when the tooltip is opened.

**`aria-label`**
Type: `string`
Description: Custom label for the tooltip.

**`positioning`**
Type: `PositioningOptions`
Description: The user provided options used to position the popover content

**`disabled`**
Type: `boolean`
Description: Whether the tooltip is disabled

**`open`**
Type: `boolean`
Description: The controlled open state of the tooltip

**`defaultOpen`**
Type: `boolean`
Description: The initial open state of the tooltip when rendered.
Use when you don't need to control the open state of the tooltip.

**`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 tooltip `api` exposes the following methods:

**`open`**
Type: `boolean`
Description: Whether the tooltip is open.

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open the tooltip.

**`reposition`**
Type: `(options?: Partial<PositioningOptions>) => void`
Description: Function to reposition the popover

### Data Attributes

**`Trigger`**

**`data-scope`**: tooltip
**`data-part`**: trigger
**`data-expanded`**: Present when expanded
**`data-state`**: "open" | "closed"

**`Content`**

**`data-scope`**: tooltip
**`data-part`**: content
**`data-state`**: "open" | "closed"
**`data-placement`**: The placement of the content

## Accessibility

### Keyboard Interactions

**`Tab`**
Description: Opens/closes the tooltip without delay.

**`Escape`**
Description: If open, closes the tooltip without delay.



# Tour

A tour is an onboarding component used to guide users through a new product
feature or series of steps. It is often used to boost feature discoverability or
onboard new users by highlighting specific elements on the page.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/tour)
[Logic Visualizer](https://zag-visualizer.vercel.app/tour)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tour)



**Features**

- Support for different step types such as "dialog", "floating", "tooltip" or
  "wait".
- Support for customizable content per step.
- Wait steps for waiting for a specific selector to appear on the page before
  showing the next step.
- Flexible positioning of the tour dialog per step.
- Progress tracking shows users their progress through the tour.

## Installation

To use the tooltip machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tour @zag-js/react
# or
yarn add @zag-js/tour @zag-js/react
```


This command will install the framework agnostic tour logic and the reactive
utilities for your framework of choice.

## Anatomy

To set up the tooltip 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

First, import the tooltip package into your project

```jsx
import * as tour from "@zag-js/tour"
```

The tour package exports two key functions:

- `machine` — The state machine logic for the tour widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
tour machine in your project 🔥

```tsx
import * as tour from "@zag-js/tour"
import { useMachine, normalizeProps, Portal } from "@zag-js/react"
import { useId } from "react"

function Tour() {
  const service = useMachine(tour.machine, { id: useId(), steps })
  const api = tour.connect(service, normalizeProps)
  return (
    <div>
      <div>
        <button onClick={() => api.start()}>Start Tour</button>
        <div id="step-1">Step 1</div>
      </div>
      {api.step && api.open && (
        <Portal>
          {api.step.backdrop && <div {...api.getBackdropProps()} />}
          <div {...api.getSpotlightProps()} />
          <div {...api.getPositionerProps()}>
            <div {...api.getContentProps()}>
              {api.step.arrow && (
                <div {...api.getArrowProps()}>
                  <div {...api.getArrowTipProps()} />
                </div>
              )}

              <p {...api.getTitleProps()}>{api.step.title}</p>
              <div {...api.getDescriptionProps()}>{api.step.description}</div>
              <div {...api.getProgressTextProps()}>{api.getProgressText()}</div>

              {api.step.actions && (
                <div>
                  {api.step.actions.map((action) => (
                    <button
                      key={action.label}
                      {...api.getActionTriggerProps({ action })}
                    >
                      {action.label}
                    </button>
                  ))}
                </div>
              )}

              <button {...api.getCloseTriggerProps()}>X</button>
            </div>
          </div>
        </Portal>
      )}
    </div>
  )
}

const steps: tour.StepDetails[] = [
  {
    type: "dialog",
    id: "start",
    title: "Ready to go for a ride",
    description: "Let's take the tour component for a ride and have some fun!",
    actions: [{ label: "Let's go!", action: "next" }],
  },
  {
    id: "logic",
    title: "Step 1",
    description: "This is the first step",
    target: () => document.querySelector("#step-1"),
    placement: "bottom",
    actions: [
      { label: "Prev", action: "prev" },
      { label: "Next", action: "next" },
    ],
  },
  {
    type: "dialog",
    id: "end",
    title: "Amazing! You got to the end",
    description: "Like what you see? Now go ahead and use it in your project.",
    actions: [{ label: "Finish", action: "dismiss" }],
  },
]
```


## Using step types

The tour machine supports different types of steps, allowing you to create a
diverse and interactive tour experience. The available step types are defined in
the `StepType` type:

- `"tooltip"`: Displays the step content as a tooltip, typically positioned near
  the target element.

- `"dialog"`: Shows the step content in a modal dialog centered on screen,
  useful for starting or ending the tour. This usually don't have a `target`
  defined.

- `"floating"`: Presents the step content as a floating element, which can be
  positioned flexibly on the screen. This usually don't have a `target` defined.

- `"wait"`: A special type that waits for a specific condition before proceeding
  to the next step.

```tsx
const steps: tour.StepDetails[] = [
  // Tooltip step
  {
    id: "step-1",
    type: "tooltip",
    placement: "top-start",
    target: () => document.querySelector("#target-1"),
    title: "Tooltip Step",
    description: "This is a tooltip step",
  },

  // Dialog step
  {
    id: "step-2",
    type: "dialog",
    title: "Dialog Step",
    description: "This is a dialog step",
  },

  // Floating step
  {
    id: "step-3",
    type: "floating",
    placement: "top-start",
    title: "Floating Step",
    description: "This is a floating step",
  },

  // Wait step
  {
    id: "step-4",
    type: "wait",
    title: "Wait Step",
    description: "This is a wait step",
    effect({ next }) {
      // do something and go next
      // you can also return a cleanup
    },
  },
]
```

## Configuring actions

Every step supports a list of actions that are rendered in the step footer.Use
the `actions` property to define each action.

```tsx
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "dialog",
    title: "Dialog Step",
    description: "This is a dialog step",
    actions: [{ label: "Show me a tour!", action: "next" }],
  },
]
```

## Changing tooltip placement

Use the `placement` property to define the placement of the tooltip.

```tsx {5}
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "tooltip",
    placement: "top-start",
    // ...
  },
]
```

## Hiding the arrow

Set `arrow: false` in the step property to hide the tooltip arrow. This is only
useful for tooltip steps.

```tsx {5}
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "tooltip",
    arrow: false,
  },
]
```

## Hiding the backdrop

Set `backdrop: false` in the step property to hide the backdrop. This applies to
all step types except the `wait` step.

```tsx {5}
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "dialog",
    backdrop: false,
  },
]
```

## Step Effects

Step effects are functions that are called before a step is opened. They are
useful for adding custom logic to a step.

This function provides the following methods:

- `next()`: Call this method to move to the next step.
- `show()`: Call this method to show the current step.
- `update(details: StepDetails)`: Call this method to update the details of the
  current step (say, after data has been fetched).

```tsx
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "tooltip",
    effect({ next, show, update }) {
      fetchData().then((res) => {
        // update the step details
        update({ title: res.title })
        // then show show the step
        show()
      })

      return () => {
        // cleanup fetch data
      }
    },
  },
]
```

## Wait Steps

Wait steps are useful when you need to wait for a specific condition before
proceeding to the next step.

Use the step `effect` function to perform an action and then call `next()` to
move to the next step.

> **Note:** You cannot call `show()` in a wait step.

```tsx
const steps: tour.StepDetails[] = [
  {
    id: "step-1",
    type: "wait",
    effect({ next }) {
      const button = document.querySelector("#button")
      const listener = () => next()
      button.addEventListener("click", listener)
      return () => button.removeEventListener("click", listener)
    },
  },
]
```

## Showing progress dots

Use the `api.getProgressPercent()` to show the progress dots.

```tsx
const ProgressBar = () => {
  const service = useMachine(tour.machine, { steps: [] })
  const api = tour.connect(service, normalizeProps)
  return <div>{api.getProgressPercent()}</div>
}
```

## Tracking the lifecycle

As the tour is progressed, events are fired and you can track the lifecycle of
the tour. Here's are the events you can listen to:

- `onStepChange`: Fires when the current step changes.
- `onStatusChange`: Fires when the status of the tour changes.

```tsx
const Lifecycle = () => {
  const service = useMachine(tour.machine, {
    steps: [],
    onStepChange(details) {
      // => { stepId: "step-1", stepIndex: 0, totalSteps: 3, complete: false, progress: 0 }
      console.log(details)
    },
    onStatusChange(status) {
      // => { status: "started" | "skipped" | "completed" | "dismissed" | "not-found" }
      console.log(status)
    },
  })

  const api = tour.connect(service, normalizeProps)
  // ...
}
```

## Styling guide

### Prerequisites

Ensure the `box-sizing` is set to `border-box` for the means of measuring the
tour target.

```css
* {
  box-sizing: border-box;
}
```

Ensure the `body` has a `position` of `relative`.

```css
body {
  position: relative;
}
```

### Overview

Each tour part has a `data-part` attribute that can be used to style them in the
DOM.

```css
[data-scope="tour"][data-part="content"] {
  /* styles for the content part */
}

[data-scope="tour"][data-part="positioner"] {
  /* styles for the positioner part */
}

[data-scope="tour"][data-part="arrow"] {
  /* styles for the arrow part */
}

[data-scope="tour"][data-part="title"] {
  /* styles for the title part */
}

[data-scope="tour"][data-part="description"] {
  /* styles for the description part */
}

[data-scope="tour"][data-part="progress-text"] {
  /* styles for the progress text part */
}

[data-scope="tour"][data-part="action-trigger"] {
  /* styles for the action trigger part */
}

[data-scope="tour"][data-part="backdrop"] {
  /* styles for the backdrop part */
}
```

### Step types

The tour component supports two types: `dialog` and `floating`. You can apply
specific styles based on the tour type:

```css
[data-scope="tour"][data-part="content"][data-type="dialog"] {
  /* styles for content when step is dialog type */
}

[data-scope="tour"][data-part="content"][data-type="floating"] {
  /* styles for content when step is floating type */
}

[data-scope="tour"][data-part="positioner"][data-type="dialog"] {
  /* styles for positioner when step is dialog type */
}

[data-scope="tour"][data-part="positioner"][data-type="floating"] {
  /* styles for positioner when step is floating type */
}
```

### Placement Styles

For floating type tours, you can style based on the placement using the
`data-placement` attribute:

```css
[data-scope="tour"][data-part="positioner"][data-type="floating"][data-placement*="bottom"] {
  /* styles for bottom placement */
}

[data-scope="tour"][data-part="positioner"][data-type="floating"][data-placement*="top"] {
  /* styles for top placement */
}

[data-scope="tour"][data-part="positioner"][data-type="floating"][data-placement*="start"] {
  /* styles for start placement */
}

[data-scope="tour"][data-part="positioner"][data-type="floating"][data-placement*="end"] {
  /* styles for end placement */
}
```

## Methods and Properties

### Machine Context

The tour machine exposes the following context properties:

**`ids`**
Type: `Partial<{ content: string; title: string; description: string; positioner: string; backdrop: string; arrow: string; }>`
Description: The ids of the elements in the tour. Useful for composition.

**`steps`**
Type: `StepDetails[]`
Description: The steps of the tour

**`stepId`**
Type: `string`
Description: The id of the currently highlighted step

**`onStepChange`**
Type: `(details: StepChangeDetails) => void`
Description: Callback when the highlighted step changes

**`onStepsChange`**
Type: `(details: StepsChangeDetails) => void`
Description: Callback when the steps change

**`onStatusChange`**
Type: `(details: StatusChangeDetails) => void`
Description: Callback when the tour is opened or closed

**`closeOnInteractOutside`**
Type: `boolean`
Description: Whether to close the tour when the user clicks outside the tour

**`closeOnEscape`**
Type: `boolean`
Description: Whether to close the tour when the user presses the escape key

**`keyboardNavigation`**
Type: `boolean`
Description: Whether to allow keyboard navigation (right/left arrow keys to navigate between steps)

**`preventInteraction`**
Type: `boolean`
Description: Prevents interaction with the rest of the page while the tour is open

**`spotlightOffset`**
Type: `Point`
Description: The offsets to apply to the spotlight

**`spotlightRadius`**
Type: `number`
Description: The radius of the spotlight clip path

**`translations`**
Type: `IntlTranslations`
Description: The translations for the tour

**`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 time picker `api` exposes the following methods:

**`open`**
Type: `boolean`
Description: Whether the tour is open

**`totalSteps`**
Type: `number`
Description: The total number of steps

**`stepIndex`**
Type: `number`
Description: The index of the current step

**`step`**
Type: `StepDetails`
Description: The current step details

**`hasNextStep`**
Type: `boolean`
Description: Whether there is a next step

**`hasPrevStep`**
Type: `boolean`
Description: Whether there is a previous step

**`firstStep`**
Type: `boolean`
Description: Whether the current step is the first step

**`lastStep`**
Type: `boolean`
Description: Whether the current step is the last step

**`addStep`**
Type: `(step: StepDetails) => void`
Description: Add a new step to the tour

**`removeStep`**
Type: `(id: string) => void`
Description: Remove a step from the tour

**`updateStep`**
Type: `(id: string, stepOverrides: Partial<StepDetails>) => void`
Description: Update a step in the tour with partial details

**`setSteps`**
Type: `(steps: StepDetails[]) => void`
Description: Set the steps of the tour

**`setStep`**
Type: `(id: string) => void`
Description: Set the current step of the tour

**`start`**
Type: `(id?: string) => void`
Description: Start the tour at a specific step (or the first step if not provided)

**`isValidStep`**
Type: `(id: string) => boolean`
Description: Check if a step is valid

**`isCurrentStep`**
Type: `(id: string) => boolean`
Description: Check if a step is visible

**`next`**
Type: `() => void`
Description: Move to the next step

**`prev`**
Type: `() => void`
Description: Move to the previous step

**`getProgressText`**
Type: `() => string`
Description: Returns the progress text

**`getProgressPercent`**
Type: `() => number`
Description: Returns the progress percent



# Tree View

The TreeView component provides a hierarchical view of data, similar to a file
system explorer. It allows users to expand and collapse branches, select
individual or multiple nodes, and traverse the hierarchy using keyboard
navigation.

## Resources


[Latest version: v1.5.0](https://www.npmjs.com/package/@zag-js/tree-view)
[Logic Visualizer](https://zag-visualizer.vercel.app/tree-view)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tree-view)



**Features**

- Display hierarchical data in a tree structure.
- Expand or collapse nodes
- Support for keyboard navigation
- Select single or multiple nodes (depending on the selection mode)
- Perform actions on the nodes, such as deleting them or performing some other
  operation.

## Installation

To use the tree view machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/tree-view @zag-js/react
# or
yarn add @zag-js/tree-view @zag-js/react
```


This command will install the framework agnostic tree view logic and the
reactive utilities for your framework of choice.

## Anatomy

To set up the tree view correctly, you'll need to understand its anatomy.



## Usage

First, import the tree view package into your project

```jsx
import * as tree from "@zag-js/tree-view"
```

The tree view package exports two key functions:

- `machine` — The state machine logic for the tree view widget.
- `connect` — The function that translates the machine's state to JSX attributes
  and event handlers.

Next, import the required hooks and functions for your framework and use the
tree view machine in your project 🔥

### Create the tree collection

Use the `collection` function to create a tree collection. This create a tree
factory that the component uses for traversal.

```ts
import * as tree from "@zag-js/tree-view"

interface Node {
  id: string
  name: string
  children?: Node[]
}

const collection = tree.collection<Node>({
  nodeToValue: (node) => node.id,
  nodeToString: (node) => node.name,
  rootNode: {
    id: "ROOT",
    name: "",
    children: [
      {
        id: "node_modules",
        name: "node_modules",
        children: [
          { id: "node_modules/zag-js", name: "zag-js" },
          { id: "node_modules/pandacss", name: "panda" },
          {
            id: "node_modules/@types",
            name: "@types",
            children: [
              { id: "node_modules/@types/react", name: "react" },
              { id: "node_modules/@types/react-dom", name: "react-dom" },
            ],
          },
        ],
      },
    ],
  },
})
```

### Create the tree view

Pass the tree collection to the machine to create the tree view.

```tsx
import { normalizeProps, useMachine } from "@zag-js/react"
import * as tree from "@zag-js/tree-view"
import { FileIcon, FolderIcon, ChevronRightIcon } from "lucide-react"
import { useId } from "react"

// 1. Create the tree collection

interface Node {
  id: string
  name: string
  children?: Node[]
}

const collection = tree.collection<Node>({
  // ...
})

// 2. Create the recursive tree node

interface TreeNodeProps {
  node: Node
  indexPath: number[]
  api: tree.Api
}

const TreeNode = (props: TreeNodeProps): JSX.Element => {
  const { node, indexPath, api } = props

  const nodeProps = { indexPath, node }
  const nodeState = api.getNodeState(nodeProps)

  if (nodeState.isBranch) {
    return (
      <div {...api.getBranchProps(nodeProps)}>
        <div {...api.getBranchControlProps(nodeProps)}>
          <FolderIcon />
          <span {...api.getBranchTextProps(nodeProps)}>{node.name}</span>
          <span {...api.getBranchIndicatorProps(nodeProps)}>
            <ChevronRightIcon />
          </span>
        </div>
        <div {...api.getBranchContentProps(nodeProps)}>
          <div {...api.getBranchIndentGuideProps(nodeProps)} />
          {node.children?.map((childNode, index) => (
            <TreeNode
              key={childNode.id}
              node={childNode}
              indexPath={[...indexPath, index]}
              api={api}
            />
          ))}
        </div>
      </div>
    )
  }

  return (
    <div {...api.getItemProps(nodeProps)}>
      <FileIcon /> {node.name}
    </div>
  )
}

// 3. Create the tree view

export function TreeView() {
  const service = useMachine(tree.machine, { id: useId(), collection })
  const api = tree.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <h3 {...api.getLabelProps()}>My Documents</h3>
      <div {...api.getTreeProps()}>
        {collection.rootNode.children?.map((node, index) => (
          <TreeNode key={node.id} node={node} indexPath={[index]} api={api} />
        ))}
      </div>
    </div>
  )
}
```


## Expanding and Collapsing Nodes

By default, the tree view will expand or collapse when clicking the branch
control. To control the expanded state of the tree view, use the `api.expand`
and `api.collapse` methods.

```tsx
api.expand(["node_modules/pandacss"]) // expand a single node
api.expand() // expand all nodes

api.collapse(["node_modules/pandacss"]) // collapse a single node
api.collapse() // collapse all nodes
```

## Multiple selection

The tree view supports multiple selection. To enable this, set the
`selectionMode` to `multiple`.

```tsx {2}
const service = useMachine(tree.machine, {
  selectionMode: "multiple",
})
```

## Setting the default expanded nodes

To set the default expanded nodes, use the `expandedValue` context property.

```tsx {2}
const service = useMachine(tree.machine, {
  defaultExpandedValue: ["node_modules/pandacss"],
})
```

## Setting the default selected nodes

To set the default selected nodes, use the `selectedValue` context property.

```tsx {2}
const service = useMachine(tree.machine, {
  defaultSelectedValue: ["node_modules/pandacss"],
})
```

## Indentation Guide

When rendering a branch node in the tree view, you can render the `indentGuide`
element by using the `api.getBranchIndentGuideProps()` function.

```tsx {9}
<div {...api.getBranchProps(nodeProps)}>
  <div {...api.getBranchControlProps(nodeProps)}>
    <FolderIcon />
    {node.name}
    <span {...api.getBranchIndicatorProps(nodeProps)}>
      <ChevronRightIcon />
    </span>
  </div>
  <div {...api.getBranchContentProps(nodeProps)}>
    <div {...api.getBranchIndentGuideProps(nodeProps)} />
    {node.children.map((childNode, index) => (
      <TreeNode
        key={childNode.id}
        node={childNode}
        indexPath={[...indexPath, index]}
        api={api}
      />
    ))}
  </div>
</div>
```

## Listening for selection

When a node is selected, the `onSelectionChange` callback is invoked with the
selected nodes.

```jsx {2-5}
const service = useMachine(tree.machine, {
  onSelectionChange(details) {
    console.log("selected nodes:", details)
  },
})
```

## Listening for expanding and collapsing

When a node is expanded or collapsed, the `onExpandedChange` callback is invoked
with the expanded nodes.

```jsx {2-5}
const service = useMachine(tree.machine, {
  onExpandedChange(details) {
    console.log("expanded nodes:", details)
  },
})
```

## Methods and Properties

### Machine Context

The tree view machine exposes the following context properties:

**`collection`**
Type: `TreeCollection<T>`
Description: The tree collection data

**`ids`**
Type: `Partial<{ root: string; tree: string; label: string; node(value: string): string; }>`
Description: The ids of the tree elements. Useful for composition.

**`expandedValue`**
Type: `string[]`
Description: The controlled expanded node ids

**`defaultExpandedValue`**
Type: `string[]`
Description: The initial expanded node ids when rendered.
Use when you don't need to control the expanded node ids.

**`selectedValue`**
Type: `string[]`
Description: The controlled selected node ids

**`defaultSelectedValue`**
Type: `string[]`
Description: The initial selected node ids when rendered.
Use when you don't need to control the selected node ids.

**`focusedValue`**
Type: `string`
Description: The id of the focused node

**`selectionMode`**
Type: `"single" | "multiple"`
Description: Whether the tree supports multiple selection
- "single": only one node can be selected
- "multiple": multiple nodes can be selected

**`onExpandedChange`**
Type: `(details: ExpandedChangeDetails) => void`
Description: Called when the tree is opened or closed

**`onSelectionChange`**
Type: `(details: SelectionChangeDetails) => void`
Description: Called when the selection changes

**`onFocusChange`**
Type: `(details: FocusChangeDetails) => void`
Description: Called when the focused node changes

**`expandOnClick`**
Type: `boolean`
Description: Whether clicking on a branch should open it or not

**`typeahead`**
Type: `boolean`
Description: Whether the tree supports typeahead search

**`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 tree view `api` exposes the following methods:

**`collection`**
Type: `TreeCollection<V>`
Description: The tree collection data

**`expandedValue`**
Type: `string[]`
Description: The id of the expanded nodes

**`setExpandedValue`**
Type: `(value: string[]) => void`
Description: Function to set the expanded value

**`selectedValue`**
Type: `string[]`
Description: The id of the selected nodes

**`setSelectedValue`**
Type: `(value: string[]) => void`
Description: Function to set the selected value

**`getVisibleNodes`**
Type: `() => V[]`
Description: Function to get the visible nodes

**`expand`**
Type: `(value?: string[]) => void`
Description: Function to expand nodes.
If no value is provided, all nodes will be expanded

**`collapse`**
Type: `(value?: string[]) => void`
Description: Function to collapse nodes
If no value is provided, all nodes will be collapsed

**`select`**
Type: `(value?: string[]) => void`
Description: Function to select nodes
If no value is provided, all nodes will be selected

**`deselect`**
Type: `(value?: string[]) => void`
Description: Function to deselect nodes
If no value is provided, all nodes will be deselected

**`focus`**
Type: `(value: string) => void`
Description: Function to focus an item node

**`selectParent`**
Type: `(value: string) => void`
Description: Function to select the parent node of the focused node

**`expandParent`**
Type: `(value: string) => void`
Description: Function to expand the parent node of the focused node

### Data Attributes

**`Item`**

**`data-scope`**: tree-view
**`data-part`**: item
**`data-path`**: The path of the item
**`data-value`**: The value of the item
**`data-focus`**: Present when focused
**`data-selected`**: Present when selected
**`data-disabled`**: Present when disabled
**`data-depth`**: The depth of the item

**`ItemText`**

**`data-scope`**: tree-view
**`data-part`**: item-text
**`data-disabled`**: Present when disabled
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused

**`ItemIndicator`**

**`data-scope`**: tree-view
**`data-part`**: item-indicator
**`data-disabled`**: Present when disabled
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused

**`Branch`**

**`data-scope`**: tree-view
**`data-part`**: branch
**`data-depth`**: The depth of the item
**`data-branch`**: 
**`data-value`**: The value of the item
**`data-path`**: The path of the item
**`data-selected`**: Present when selected
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled

**`BranchIndicator`**

**`data-scope`**: tree-view
**`data-part`**: branch-indicator
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused

**`BranchTrigger`**

**`data-scope`**: tree-view
**`data-part`**: branch-trigger
**`data-disabled`**: Present when disabled
**`data-state`**: "open" | "closed"
**`data-value`**: The value of the item

**`BranchControl`**

**`data-scope`**: tree-view
**`data-part`**: branch-control
**`data-path`**: The path of the item
**`data-state`**: "open" | "closed"
**`data-disabled`**: Present when disabled
**`data-selected`**: Present when selected
**`data-focus`**: Present when focused
**`data-value`**: The value of the item
**`data-depth`**: The depth of the item

**`BranchText`**

**`data-scope`**: tree-view
**`data-part`**: branch-text
**`data-disabled`**: Present when disabled
**`data-state`**: "open" | "closed"

**`BranchContent`**

**`data-scope`**: tree-view
**`data-part`**: branch-content
**`data-state`**: "open" | "closed"
**`data-depth`**: The depth of the item
**`data-path`**: The path of the item
**`data-value`**: The value of the item

**`BranchIndentGuide`**

**`data-scope`**: tree-view
**`data-part`**: branch-indent-guide
**`data-depth`**: The depth of the item

## Accessibility

Adheres to the
[Tree View WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview).

### Keyboard Interactions

**`Tab`**
Description: Moves focus to the tree view, placing the first tree view item in focus.

**`Enter + Space`**
Description: Selects the item or branch node

**`ArrowDown`**
Description: Moves focus to the next node

**`ArrowUp`**
Description: Moves focus to the previous node

**`ArrowRight`**
Description: When focus is on a closed branch node, opens the branch.<br> When focus is on an open branch node, moves focus to the first item node.

**`ArrowLeft`**
Description: When focus is on an open branch node, closes the node.<br> When focus is on an item or branch node, moves focus to its parent branch node.

**`Home`**
Description: Moves focus to first node without opening or closing a node.

**`End`**
Description: Moves focus to the last node that can be focused without expanding any nodes that are closed.

**`a-z + A-Z`**
Description: Focus moves to the next node with a name that starts with the typed character. The search logic ignores nodes that are descendants of closed branch.

**`*`**
Description: Expands all sibling nodes that are at the same depth as the focused node.

**`Shift + ArrowDown`**
Description: Moves focus to and toggles the selection state of the next node.

**`Shift + ArrowUp`**
Description: Moves focus to and toggles the selection state of the previous node.

**`Ctrl + A`**
Description: Selects all nodes in the tree. If all nodes are selected, unselects all nodes.