# 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";
Actions
Danger zone
```
### 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