# Listbox
**Category**: react
**URL**: https://www.heroui.com/docs/react/migration/listbox
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/migration/(components)/listbox.mdx
> Migration guide for Listbox (renamed to ListBox with a capital "B") from HeroUI v2 to v3
***
Refer to the [v3 ListBox documentation](/docs/react/components/listbox) for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
## Structure Changes
### v2: Separate Components
In v2, Listbox used separate components:
```tsx
import { Listbox, ListboxItem, ListboxSection } from "@heroui/react";
export default function App() {
return (
Item 1
);
}
```
### v3: Compound Components
In v3, ListBox uses compound components:
```tsx
import { ListBox, Label } from "@heroui/react";
export default function App() {
return (
);
}
```
## Key Changes
### 1. Component Naming
**v2:** `Listbox`, `ListboxItem`, `ListboxSection`
**v3:** `ListBox`, `ListBox.Item`, `ListBox.Section`
### 2. Item Identification
**v2:** React's `key` was used for both list reconciliation and item identity (selection, focus).
**v3:** Use `id` for state/focus and `textValue` for accessibility (when content isn't plain text); keep React's `key` on items in lists.
### 3. Prop Changes
| v2 Prop | v3 Location | Notes |
|---------|-------------|-------|
| `key` (for state) | `ListBox.Item` | Use `id` for item identity (state) |
| - | `textValue` (on ListBox.Item) | For accessibility (type-ahead) |
| `variant`, `color` | `variant` on `ListBox` or `ListBox.Item` | Simplified to `"default"` \| `"danger"` (no `color` prop) |
| `onAction` | `ListBox` | Callback fired when an item is pressed (`(key: Key) => void`) |
| `disabledKeys` | `ListBox` | Same — set of keys for items that should be non-interactive |
| `startContent`, `endContent` | - | Place icons manually in item content |
| `description` | `Description` | Use `Description` component |
| `title` (on Section) | `Header` | Use `Header` component |
| `topContent`, `bottomContent` | - | Removed (handle separately) |
| `itemClasses`, `classNames` | - | Use `className` on parts |
| `hideSelectedIcon` | - | Omit `ListBox.ItemIndicator` |
| `disableAnimation` | - | Removed |
| `isVirtualized`, `virtualization` | React Aria `Virtualizer` | Use React Aria's `` wrapper (see example below) |
| `selectedKeys` | `ListBox` | Same (uses `Selection` type Set) |
## Migration Examples
### Selection
```tsx
import { useState } from "react";
{/* Single selection */}
const [singleSelected, setSingleSelected] = useState(new Set(["text"]));
Text
Number
{/* Multiple selection */}
const [multiSelected, setMultiSelected] = useState(new Set(["text"]));
Text
Number
```
```tsx
import { useState } from "react";
import type { Selection } from "@heroui/react";
{/* Single selection */}
const [singleSelected, setSingleSelected] = useState(new Set(["text"]));
{/* Multiple selection */}
const [multiSelected, setMultiSelected] = useState(new Set(["text"]));
```
### With Description
```tsx
New file
```
```tsx
import { Description, Label } from "@heroui/react";
Create a new file
```
### With Icons
```tsx
}
>
New file
```
```tsx
```
### With Sections
```tsx
New file
Edit file
Delete
```
```tsx
import { Header, Label, Separator } from "@heroui/react";
```
### With Custom Indicator
```tsx
}
>
Item 1
```
```tsx
{({isSelected}) =>
isSelected ? : null
}
```
### Variant Prop
In v3, both `ListBox` and `ListBox.Item` accept a `variant` prop with values `"default"` (default) or `"danger"`. Setting `variant` on the root `ListBox` applies to all items; setting it on an individual `ListBox.Item` overrides the root value for that item.
```tsx
{/* Root-level variant — all items inherit "danger" styling */}
{/* Per-item variant */}
```
### onAction Handler
The `onAction` callback is fired when an item is pressed (click or Enter). It receives the item's `id` as a `Key`.
```tsx
alert(`Action on ${key}`)}>
```
### Disabled Keys
Use `disabledKeys` to make specific items non-interactive:
```tsx
```
### Render Props on ListBox.Item
`ListBox.Item` supports render props, giving you access to the current interaction state. The available render prop values are `isSelected`, `isFocused`, `isDisabled`, and `isPressed`:
```tsx
{({isSelected, isFocused, isDisabled, isPressed}) => (
<>
{isSelected && }
>
)}
```
### Virtualization
Virtualization is **still supported** in v3 via React Aria's `` component. Wrap your `ListBox` items with `Virtualizer` for efficient rendering of large lists:
```tsx
import {Virtualizer} from "react-aria-components";
{(item) => (
)}
```
## Component Anatomy
The v3 ListBox follows this structure:
```
ListBox (Root)
├── ListBox.Item
│ ├── Icon (optional, manual placement)
│ ├── Label (required)
│ ├── Description (optional)
│ └── ListBox.ItemIndicator (optional)
└── ListBox.Section (optional)
├── Header (optional)
└── ListBox.Item
```
## Summary
1. **Component Naming**: `Listbox` → `ListBox`, `ListboxItem` → `ListBox.Item`, `ListboxSection` → `ListBox.Section`
2. **Item Structure**: Must use `Label`, `Description`, `ListBox.ItemIndicator` components
3. **Icons**: Manual placement instead of `startContent`/`endContent` props
4. **Sections**: Use `Header` component instead of `title` prop
5. **Variant Prop**: `variant` and `color` replaced by a single `variant` prop (`"default"` | `"danger"`) on both `ListBox` and `ListBox.Item`
6. **onAction**: New `onAction` callback on `ListBox` for item press handling
7. **disabledKeys**: Supported on `ListBox` to disable specific items
8. **Render Props**: `ListBox.Item` provides `isSelected`, `isFocused`, `isDisabled`, `isPressed` via render props
9. **Content Props Removed**: `topContent`, `bottomContent` - handle separately
10. **Virtualization**: Still supported via React Aria's `` component (replaces `isVirtualized` prop)
11. **Selection Type**: Uses `Selection` type (Set) instead of arrays