# or
yarn add @zag-js/listbox @zag-js/react
```

## Anatomy

To set up the listbox 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 listbox package into your project

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

The listbox package exports two key functions:

- `machine` â The state machine logic for the listbox 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
listbox machine in your project ð¥

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

const data = [
  { label: "Nigeria", value: "NG" },
  { label: "United States", value: "US" },
  { label: "Canada", value: "CA" },
  { label: "Japan", value: "JP" },
]

function Listbox() {
  const collection = listbox.collection({ items: data })

  const service = useMachine(listbox.machine, {
    id: useId(),
    collection,
  })

  const api = listbox.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Select country</label>
      <ul {...api.getContentProps()}>
        {data.map((item) => (
          <li key={item.value} {...api.getItemProps({ item })}>
            <span {...api.getItemTextProps({ item })}>{item.label}</span>
            <span {...api.getItemIndicatorProps({ item })}>â</span>
          </li>
        ))}
      </ul>
    </div>
  )
}
```

### Setting the initial selection

To set the initial selection, you can use the `defaultValue` property.

```tsx
const service = useMachine(listbox.machine, {
  // ...
  defaultValue: ["item-1", "item-2"],
})
```

### Controlling the selection

To control the selection programmatically, you can use the `value` and
`onValueChange` properties.

```tsx
const service = useMachine(listbox.machine, {
  value: ["item-1", "item-2"],
  onValueChange: (value) => {
    console.log(value)
  },
})
```

### Filtering

The listbox component supports filtering of items via `api.getInputProps`.
Here's an example of how to support searching through a list of items.

```tsx
import * as listbox from "@zag-js/listbox"
import { createFilter } from "@zag-js/i18n-utils"
import { normalizeProps, useMachine } from "@zag-js/react"
import { useId, useMemo, useState } from "react"

interface Item {
  label: string
  value: string
}

const data: Item[] = [
  { label: "Nigeria", value: "NG" },
  { label: "United States", value: "US" },
  { label: "Canada", value: "CA" },
  { label: "Japan", value: "JP" },
]

const filter = createFilter({ sensitivity: "base" })

function ListboxFiltering() {
  const [search, setSearch] = useState("")

  const collection = useMemo(() => {
    const items = data.filter((item) => filter.startsWith(item.label, search))
    return listbox.collection({ items })
  }, [search])

  const service = useMachine(listbox.machine as listbox.Machine<Item>, {
    collection,
    id: useId(),
    typeahead: false,
  })

  const api = listbox.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <input
        {...api.getInputProps({ autoHighlight: true })}
        onChange={(e) => setSearch(e.target.value)}
        value={search}
      />
      <ul {...api.getContentProps()}>
        {collection.items.map((item) => (
          <li key={item.value} {...api.getItemProps({ item })}>
            <span {...api.getItemTextProps({ item })}>{item.label}</span>
            <span {...api.getItemIndicatorProps({ item })}>â</span>
          </li>
        ))}
      </ul>
    </div>
  )
}
```

### Selecting multiple items

To enable multiple selection, set the `selectionMode` property to `multiple` or
`extended`.

```tsx
const service = useMachine(listbox.machine, {
  // ...
  selectionMode: "multiple",
})
```

### Selection Modes

By default, a user can select a single item in a listbox. You can set the
`selectionMode` property to a SelectionMode enumeration value to enable
multi-selection. Here are the selection mode values.

- **single**: A user can select a single item using the space bar, mouse click,
  or touch tap.
- **multiple**: A user can select multiple items using the space bar, mouse
  click, or touch tap to toggle selection on the focused item. Using the arrow
  keys, a user can move focus independently of selection.
- **extended**: With no modifier keys like `Ctrl`, `Cmd` or `Shift`: the
  behavior is the same as single selection.

```tsx
const service = useMachine(listbox.machine, {
  // ...
  selectionMode: "extended",
})
```

### Disabling items

To disable an item, you can use the `disabled` property.

```tsx
api.getItemProps({
  // ...
  disabled: true,
})
```

To disable the entire listbox, you can use the `disabled` property.

```tsx
const service = useMachine(listbox.machine, {
  disabled: true,
})
```

### Grid layout

To enable a grid layout, provide a grid collection to the `collection` property.

```tsx
const service = useMachine(listbox.machine, {
  collection: listbox.gridCollection({
    items: [],
    columnCount: 3,
  }),
})
```

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

const data = [
  { label: "Red", value: "red" },
  { label: "Green", value: "green" },
  { label: "Blue", value: "blue" },
  { label: "Yellow", value: "yellow" },
  { label: "Purple", value: "purple" },
  { label: "Orange", value: "orange" },
]

function ListboxGrid() {
  const collection = listbox.gridCollection({
    items: data,
    columnCount: 3,
  })

  const service = useMachine(listbox.machine, {
    id: useId(),
    collection,
  })

  const api = listbox.connect(service, normalizeProps)

  return (
    <div {...api.getRootProps()}>
      <label {...api.getLabelProps()}>Select color</label>
      <div
        {...api.getContentProps()}
        style={{
          display: "grid",
          gridTemplateColumns: "repeat(3, 1fr)",
          gap: "8px",
        }}
      >
        {collection.items.map((item) => (
          <div key={item.value} {...api.getItemProps({ item })}>
            <span {...api.getItemTextProps({ item })}>{item.label}</span>
            <span {...api.getItemIndicatorProps({ item })}>â</span>
          </div>
        ))}
      </div>
    </div>
  )
}
```

## Styling guide

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

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

[data-scope="listbox"][data-part="label"] {
  /* styles for the label part */
}

[data-scope="listbox"][data-part="content"] {
  /* styles for the content part */
}

[data-scope="listbox"][data-part="item"] {
  /* styles for the item part */
}

[data-scope="listbox"][data-part="itemGroup"] {
  /* styles for the item group part */
}
```

### Focused state

The focused state is applied to the item that is currently focused.

```css
[data-scope="listbox"][data-part="item"][data-focused] {
  /* styles for the focused item part */
}
```

### Selected state

The selected state is applied to the item that is currently selected.

```css
[data-scope="listbox"][data-part="item"][data-selected] {
  /* styles for the selected item part */
}
```

### Disabled state

The disabled state is applied to the item that is currently disabled.

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

## Methods and Properties

### Machine Context

The listbox machine exposes the following context properties:

**`orientation`**
Type: `"horizontal" | "vertical"`
Description: The orientation of the listbox.

**`collection`**
Type: `GridCollection<T>`
Description: The item collection

**`ids`**
Type: `Partial<{ root: string; content: string; label: string; item: (id: string | number) => string; itemGroup: (id: string | number) => string; itemGroupLabel: (id: string | number) => string; }>`
Description: The ids of the elements in the listbox. Useful for composition.

**`disabled`**
Type: `boolean`
Description: Whether the listbox is disabled

**`disallowSelectAll`**
Type: `boolean`
Description: Whether to disallow selecting all items when `meta+a` is pressed

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

**`value`**
Type: `string[]`
Description: The controlled keys of the selected items

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

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

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

**`selectionMode`**
Type: `SelectionMode`
Description: How multiple selection should behave in the listbox.

- `single`: The user can select a single item.
- `multiple`: The user can select multiple items without using modifier keys.
- `extended`: The user can select multiple items by using modifier keys.

**`scrollToIndexFn`**
Type: `(details: ScrollToIndexDetails) => void`
Description: Function to scroll to a specific index

**`selectOnHighlight`**
Type: `boolean`
Description: Whether to select the item when it is highlighted

**`deselectable`**
Type: `boolean`
Description: Whether to disallow empty selection

**`typeahead`**
Type: `boolean`
Description: Whether to enable typeahead on the listbox

**`onSelect`**
Type: `(details: SelectionDetails) => void`
Description: Function called when an item is 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 listbox `api` exposes the following methods:

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

**`clearHighlightedValue`**
Type: `VoidFunction`
Description: Function to clear the highlighted 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: `VoidFunction`
Description: Function to select all values.

**Note**: This should only be called when the selectionMode is `multiple` or `extended`.
Otherwise, an exception will be thrown.

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

**`getItemState`**
Type: `(props: ItemProps<any>) => ItemState`
Description: Returns the state of a select item

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

**`disabled`**
Type: `boolean`
Description: Whether the select is disabled

### Data Attributes

**`Root`**

**`data-scope`**: listbox
**`data-part`**: root
**`data-orientation`**: The orientation of the listbox
**`data-disabled`**: Present when disabled

**`Input`**

**`data-scope`**: listbox
**`data-part`**: input
**`data-disabled`**: Present when disabled

**`Label`**

**`data-scope`**: listbox
**`data-part`**: label
**`data-disabled`**: Present when disabled

**`ValueText`**

**`data-scope`**: listbox
**`data-part`**: value-text
**`data-disabled`**: Present when disabled

**`Item`**

**`data-scope`**: listbox
**`data-part`**: item
**`data-value`**: The value of the item
**`data-selected`**: Present when selected
**`data-layout`**: 
**`data-state`**: "checked" | "unchecked"
**`data-orientation`**: The orientation of the item
**`data-highlighted`**: Present when highlighted
**`data-disabled`**: Present when disabled

**`ItemText`**

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

**`ItemIndicator`**

**`data-scope`**: listbox
**`data-part`**: item-indicator
**`data-state`**: "checked" | "unchecked"

**`ItemGroup`**

**`data-scope`**: listbox
**`data-part`**: item-group
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the item
**`data-empty`**: Present when the content is empty

**`Content`**

**`data-scope`**: listbox
**`data-part`**: content
**`data-activedescendant`**: The id the active descendant of the content
**`data-orientation`**: The orientation of the content
**`data-layout`**: 
**`data-empty`**: Present when the content is empty

### CSS Variables

<CssVarTable name="listbox" />

## Accessibility

Adheres to the
[Listbox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/).
An accessible auto-scrolling marquee component for displaying scrolling content
like logos, announcements, or featured items.

## Resources


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



**Features**

- Smooth GPU-accelerated animations with seamless looping
- Horizontal and vertical scrolling with RTL support
- Pause on hover and keyboard focus
- Customizable speed and spacing
- Accessible and respects `prefers-reduced-motion`

## Installation

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

```bash
npm install @zag-js/marquee @zag-js/react