# ListBox **Category**: react **URL**: https://www.heroui.com/docs/react/components/list-box **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(collections)/list-box.mdx > A listbox displays a list of options and allows a user to select one or more of them *** ## Import ```tsx import { ListBox } from '@heroui/react'; ``` ### Usage ```tsx import {Avatar, Description, Label, ListBox} from "@heroui/react"; export function Default() { return ( B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
); } ``` ### Anatomy Import the ListBox component and access all parts using dot notation. ```tsx import { ListBox, Label, Description, Header } from '@heroui/react'; export default () => (
) ``` ### With Sections ```tsx "use client"; import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react"; export function WithSections() { return ( alert(`Selected item: ${key}`)} >
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### Multi Select ```tsx import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react"; export function MultiSelect() { return ( B
bob@heroui.com
F
fred@heroui.com
M
martha@heroui.com
); } ``` ### With Disabled Items ```tsx "use client"; import {Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Description, Header, Kbd, Label, ListBox, Separator, Surface} from "@heroui/react"; export function WithDisabledItems() { return ( alert(`Selected item: ${key}`)} >
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### Custom Check Icon ```tsx "use client"; import {Check} from "@gravity-ui/icons"; import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react"; export function CustomCheckIcon() { return ( B
bob@heroui.com
{({isSelected}) => (isSelected ? : null)}
F
fred@heroui.com
{({isSelected}) => (isSelected ? : null)}
M
martha@heroui.com
{({isSelected}) => (isSelected ? : null)}
); } ``` ### Controlled ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Check} from "@gravity-ui/icons"; import {Avatar, Description, Label, ListBox, Surface} from "@heroui/react"; import {useState} from "react"; export function Controlled() { const [selected, setSelected] = useState(new Set(["1"])); const selectedItems = Array.from(selected); return (
B
bob@heroui.com
{({isSelected}) => (isSelected ? : null)}
F
fred@heroui.com
{({isSelected}) => (isSelected ? : null)}
M
martha@heroui.com
{({isSelected}) => (isSelected ? : null)}

Selected: {selectedItems.length > 0 ? selectedItems.join(", ") : "None"}

); } ``` ### Custom Render Function ```tsx "use client"; import {Avatar, Description, Label, ListBox} from "@heroui/react"; export function CustomRenderFunction() { return (
} selectionMode="single" > } textValue="Bob" > B
bob@heroui.com
} textValue="Fred" > F
fred@heroui.com
} textValue="Martha" > M
martha@heroui.com
); } ``` ### 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. ```tsx "use client"; import {Description, Label, ListBox, ListLayout, Virtualizer} from "@heroui/react"; interface User { id: number; name: string; email: string; } export function Virtualization() { const firstNames = [ "Emma", "Liam", "Olivia", "Noah", "Ava", "James", "Sophia", "Oliver", "Isabella", "Lucas", "Mia", "Ethan", "Charlotte", "Mason", "Amelia", "Logan", "Harper", "Alexander", "Ella", "Benjamin", ]; const lastNames = [ "Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Anderson", "Taylor", "Thomas", "Jackson", "White", "Harris", "Clark", "Lewis", "Robinson", "Walker", ]; function generateUsers(n: number): User[] { const users: User[] = []; for (let i = 0; i < n; i++) { const firstName = firstNames[i % firstNames.length]; const lastName = lastNames[Math.floor(i / firstNames.length) % lastNames.length]; const name = `${firstName} ${lastName}`; users.push({ email: `${firstName?.toLowerCase()}.${lastName?.toLowerCase()}@acme.com`, id: i + 1, name, }); } return users; } const users = generateUsers(1000); return ( {(user) => (
{user.email}
)}
); } ``` ## Related Components - **Select**: Dropdown select control - **ComboBox**: Text input with searchable dropdown list - **Avatar**: Display user profile images ## Styling ### Passing Tailwind CSS classes ```tsx import { ListBox } from '@heroui/react'; function CustomListBox() { return ( Item 1 ); } ``` ### Customizing the component classes 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; } } ``` 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 - `.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 - `.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 - `.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 Props | 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` | - | 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` | - | Overrides the default DOM element with a custom render function.| ### ListBox.Item Props | 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 \| React.JSX.IntrinsicElements[keyof React.JSX.IntrinsicElements], renderProps: ListBoxItemRenderProps) => ReactElement` | - | Overrides the default DOM element with a custom render function.| ### ListBox.ItemIndicator Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Custom indicator content or render function | ### ListBox.Section Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Section content including Header and Items | ### RenderProps 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'; bob@heroui.com alice@heroui.com ``` ### With Sections ```tsx import { ListBox, Header, Separator } from '@heroui/react'; console.log(key)}>
Actions
New file Edit file
Danger zone
Delete
``` ### Controlled Selection ```tsx import { ListBox, Selection } from '@heroui/react'; import { useState } from 'react'; function ControlledListBox() { const [selected, setSelected] = useState(new Set(["1"])); return ( Option 1 Option 2 Option 3 ); } ``` ### Custom Indicator ```tsx import { ListBox, ListBoxItemIndicator } from '@heroui/react'; import { Icon } from '@iconify/react'; Option 1 {({isSelected}) => isSelected ? : null } ``` ## 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).