---
title: ListBox
description: A listbox displays a list of options and allows a user to select one or more of them
links:
  rac: ListBox
  source: list-box/list-box.tsx
  styles: list-box.css
  storybook: Components/Collections/ListBox
---

## Usage

```tsx
import { ListBox } from '@heroui/react';
```

<ComponentPreview
  name="list-box-default"
/>

## Anatomy

```tsx
import { ListBox, Label, Description, Header } from '@heroui/react';

export default () => (
  <ListBox>
    <ListBox.Item>
      <Label />
      <Description />
      <ListBox.ItemIndicator />
    </ListBox.Item>
    <ListBox.Section>
      <Header />
      <ListBox.Item>
        <Label />
      </ListBox.Item>
    </ListBox.Section>
  </ListBox>
)
```

## Examples

### With Disabled Items

<ComponentPreview
  name="list-box-with-disabled-items"
/>

### With Sections

<ComponentPreview
  name="list-box-with-sections"
/>

### Multi Select

<ComponentPreview
  name="list-box-multi-select"
/>

### Controlled

<ComponentPreview
  name="list-box-controlled"
/>

### Virtualization

ListBox supports virtualization through [Virtualizer](https://react-aria.adobe.com/Virtualizer), enabling efficient rendering of large datasets by displaying only the rows visible within the viewport.

<ComponentPreview 
  name="list-box-virtualization"
/>

### Custom Check Icon

<ComponentPreview
  name="list-box-custom-check-icon"
/>

### Render Function

<ComponentPreview
  name="list-box-render-function"
/>

## Customization

### Tailwind CSS

<ComponentPreview name="list-box-custom-styles" />

### Global CSS

To customize the ListBox component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes).

```css
@layer components {
  .list-box {
    @apply rounded-lg border border-border bg-surface p-2;
  }

  .list-box-item {
    @apply rounded px-2 py-1 cursor-pointer;
  }

  .list-box-item--danger {
    @apply text-danger;
  }

  .list-box-item__indicator {
    @apply text-accent;
  }
}
```

## Styling Reference

HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize.

### CSS Classes

The ListBox component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/list-box.css)):

#### Base Classes [!toc]
- `.list-box` - Base listbox container
- `.list-box-item` - Individual listbox item
- `.list-box-item__indicator` - Selection indicator icon
- `.list-box-section` - Section container for grouping items

#### Variant Classes [!toc]
- `.list-box--default` - Default variant styling
- `.list-box--danger` - Danger variant styling
- `.list-box-item--default` - Default item variant
- `.list-box-item--danger` - Danger item variant

#### State Classes [!toc]
- `.list-box-item[data-selected="true"]` - Selected item state
- `.list-box-item[data-focus-visible="true"]` - Focused item state
- `.list-box-item[data-disabled="true"]` - Disabled item state
- `.list-box-item__indicator[data-visible="true"]` - Visible indicator state

### Interactive States

The component supports both CSS pseudo-classes and data attributes for flexibility:

- **Hover**: `:hover` or `[data-hovered="true"]` on item
- **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on item
- **Selected**: `[data-selected="true"]` on item
- **Disabled**: `:disabled` or `[data-disabled="true"]` on item

## API Reference

### ListBox

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `aria-label` | `string` | - | Accessibility label for the listbox |
| `aria-labelledby` | `string` | - | ID of element that labels the listbox |
| `selectionMode` | `"none" \| "single" \| "multiple"` | `"single"` | Selection behavior |
| `selectedKeys` | `Selection` | - | Controlled selected keys |
| `defaultSelectedKeys` | `Selection` | - | Initial selected keys |
| `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when selection changes |
| `disabledKeys` | `Iterable<Key>` | - | Keys of disabled items |
| `onAction` | `(key: Key) => void` | - | Handler called when an item is activated |
| `variant` | `"default" \| "danger"` | `"default"` | Visual variant |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | ListBox items and sections |
| `render` | `DOMRenderFunction<keyof React.JSX.IntrinsicElements, ListBoxRenderProps>` | - | Overrides the default DOM element with a custom render function.|

### ListBox.Item

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `id` | `Key` | - | Unique identifier for the item |
| `textValue` | `string` | - | Text value for accessibility and typeahead |
| `isDisabled` | `boolean` | `false` | Whether this item is disabled |
| `variant` | `"default" \| "danger"` | `"default"` | Visual variant |
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Item content or render function |
| `render` | `(props: DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> \| React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], renderProps: ListBoxItemRenderProps) => ReactElement` | - | Overrides the default DOM element with a custom render function.|

### ListBox.ItemIndicator

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode \| RenderFunction` | - | Custom indicator content or render function |

### ListBox.Section

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes |
| `children` | `ReactNode` | - | Section content including Header and Items |

### Render Props

When using render functions with ListBox.Item or ListBox.ItemIndicator, these values are provided:

| Prop | Type | Description |
|------|------|-------------|
| `isSelected` | `boolean` | Whether the item is selected |
| `isFocused` | `boolean` | Whether the item is focused |
| `isDisabled` | `boolean` | Whether the item is disabled |
| `isPressed` | `boolean` | Whether the item is being pressed |

### ListLayout

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `rowHeight` | `number \| undefined` | 48 | The fixed height of a row in px. |
| `estimatedRowHeight` | `number \| undefined` | — | The estimated height of a row, when row heights are variable. |
| `headingHeight` | `number \| undefined` | 48 | The fixed height of a section header in px. |
| `estimatedHeadingHeight` | `number \| undefined` | — | The estimated height of a section header, when the height is variable. |
| `loaderHeight` | `number \| undefined` | 48 | The fixed height of a loader element in px. This loader is specifically for "load more" elements rendered when loading more rows at the root level or inside nested row/sections. |
| `dropIndicatorThickness` | `number \| undefined` | 2 | The thickness of the drop indicator. |
| `gap` | `number \| undefined` | 0 | The gap between items. |
| `padding` | `number \| undefined` | 0 | The padding around the list. |

## Examples

### Basic Usage

```tsx
import { ListBox, Label, Description } from '@heroui/react';

<ListBox aria-label="Users" selectionMode="single">
  <ListBox.Item id="1" textValue="Bob">
    <Label>Bob</Label>
    <Description>bob@heroui.com</Description>
  </ListBox.Item>
  <ListBox.Item id="2" textValue="Alice">
    <Label>Alice</Label>
    <Description>alice@heroui.com</Description>
  </ListBox.Item>
</ListBox>
```

### With Sections

```tsx
import { ListBox, Header, Separator } from '@heroui/react';

<ListBox aria-label="Actions" selectionMode="none" onAction={(key) => console.log(key)}>
  <ListBox.Section>
    <Header>Actions</Header>
    <ListBox.Item id="new" textValue="New file">New file</ListBox.Item>
    <ListBox.Item id="edit" textValue="Edit file">Edit file</ListBox.Item>
  </ListBox.Section>
  <Separator />
  <ListBox.Section>
    <Header>Danger zone</Header>
    <ListBox.Item id="delete" textValue="Delete" variant="danger">Delete</ListBox.Item>
  </ListBox.Section>
</ListBox>
```

### Controlled Selection

```tsx
import { ListBox, Selection } from '@heroui/react';
import { useState } from 'react';

function ControlledListBox() {
  const [selected, setSelected] = useState<Selection>(new Set(["1"]));

  return (
    <ListBox
      aria-label="Options"
      selectedKeys={selected}
      selectionMode="multiple"
      onSelectionChange={setSelected}
    >
      <ListBox.Item id="1" textValue="Option 1">Option 1</ListBox.Item>
      <ListBox.Item id="2" textValue="Option 2">Option 2</ListBox.Item>
      <ListBox.Item id="3" textValue="Option 3">Option 3</ListBox.Item>
    </ListBox>
  );
}
```

### Custom Indicator

```tsx
import { ListBox, ListBoxItemIndicator } from '@heroui/react';
import { Icon } from '@iconify/react';

<ListBox aria-label="Options" selectionMode="multiple">
  <ListBox.Item id="1" textValue="Option 1">
    Option 1
    <ListBox.ItemIndicator>
      {({isSelected}) =>
        isSelected ? <Icon icon="gravity-ui:check" /> : null
      }
    </ListBox.ItemIndicator>
  </ListBox.Item>
</ListBox>
```

## Accessibility

The ListBox component implements the ARIA listbox pattern and provides:

- Full keyboard navigation support
- Screen reader announcements for selection changes
- Proper focus management
- Support for disabled states
- Typeahead search functionality

For more information, see the [React Aria ListBox documentation](https://react-spectrum.adobe.com/react-aria/ListBox.html).

## Related Components

<RelatedComponents component="list-box" />
