ListBox

PreviousNext

A listbox displays a list of options and allows a user to select one or more of them.

Aardvark
Cat
Dog
Kangaroo
Panda
Snake
import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxDemo() {
  return (
    <ListBox
      aria-label="Favorite animal"
      selectionMode="single"
      className="w-64"
    >
      <ListBoxItem>Aardvark</ListBoxItem>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
      <ListBoxItem>Panda</ListBoxItem>
      <ListBoxItem>Snake</ListBoxItem>
    </ListBox>
  )
}

Installation

pnpm dlx shadcn@latest add list-box

Usage

import { ListBox, ListBoxItem } from "@/components/ui/list-box"
<ListBox aria-label="Favorite animal" selectionMode="single">
  <ListBoxItem>Aardvark</ListBoxItem>
  <ListBoxItem>Cat</ListBoxItem>
  <ListBoxItem>Dog</ListBoxItem>
  <ListBoxItem>Kangaroo</ListBoxItem>
  <ListBoxItem>Panda</ListBoxItem>
  <ListBoxItem>Snake</ListBoxItem>
</ListBox>

Features

A listbox can be built using the <select> and <option> HTML elements, but this is not possible to style consistently cross browser. ListBox helps you build accessible listbox components that can be styled as needed.

  • Item selection – Single or multiple selection, with both toggle and replace selection behaviors
  • Keyboard navigation – Arrow keys, page up/down, home/end, and typeahead search
  • Touch friendly – Selection behavior adapts based on device (mouse down vs touch up)
  • Accessible – Follows the ARIA listbox pattern with proper keyboard and screen reader support
  • Styleable – Hover, press, focus, selected, and disabled states for easy styling

Note: ListBox only handles the list itself. For a dropdown, see Select or ComboBox.

Examples

Default

Aardvark
Cat
Dog
Kangaroo
Panda
Snake
import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxDemo() {
  return (
    <ListBox
      aria-label="Favorite animal"
      selectionMode="single"
      className="w-64"
    >
      <ListBoxItem>Aardvark</ListBoxItem>
      <ListBoxItem>Cat</ListBoxItem>
      <ListBoxItem>Dog</ListBoxItem>
      <ListBoxItem>Kangaroo</ListBoxItem>
      <ListBoxItem>Panda</ListBoxItem>
      <ListBoxItem>Snake</ListBoxItem>
    </ListBox>
  )
}
<ListBox aria-label="Favorite animal" selectionMode="single" className="w-64">
  <ListBoxItem>Aardvark</ListBoxItem>
  <ListBoxItem>Cat</ListBoxItem>
  <ListBoxItem>Dog</ListBoxItem>
  <ListBoxItem>Kangaroo</ListBoxItem>
  <ListBoxItem>Panda</ListBoxItem>
  <ListBoxItem>Snake</ListBoxItem>
</ListBox>

Multiple Selection

Aardvark
Cat
Dog
Kangaroo
Panda
Snake

Selected: None

"use client"

import { useState } from "react"

import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxMultiple() {
  const [selected, setSelected] = useState<Set<string>>(new Set())

  return (
    <div className="flex flex-col gap-4">
      <ListBox
        aria-label="Favorite animals"
        selectionMode="multiple"
        selectedKeys={selected}
        onSelectionChange={(keys) => setSelected(keys as Set<string>)}
        className="w-64"
      >
        <ListBoxItem id="aardvark">Aardvark</ListBoxItem>
        <ListBoxItem id="cat">Cat</ListBoxItem>
        <ListBoxItem id="dog">Dog</ListBoxItem>
        <ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
        <ListBoxItem id="panda">Panda</ListBoxItem>
        <ListBoxItem id="snake">Snake</ListBoxItem>
      </ListBox>
      <p className="text-muted-foreground text-sm">
        Selected: {selected.size > 0 ? Array.from(selected).join(", ") : "None"}
      </p>
    </div>
  )
}
"use client"
 
import { useState } from "react"
import { ListBox, ListBoxItem } from "@/components/ui/list-box"
 
export default function Example() {
  const [selected, setSelected] = useState<Set<string>>(new Set())
 
  return (
    <ListBox
      aria-label="Favorite animals"
      selectionMode="multiple"
      selectedKeys={selected}
      onSelectionChange={(keys) => setSelected(keys as Set<string>)}
      className="w-64"
    >
      <ListBoxItem id="aardvark">Aardvark</ListBoxItem>
      <ListBoxItem id="cat">Cat</ListBoxItem>
      <ListBoxItem id="dog">Dog</ListBoxItem>
      <ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
      <ListBoxItem id="panda">Panda</ListBoxItem>
      <ListBoxItem id="snake">Snake</ListBoxItem>
    </ListBox>
  )
}

Set selectionMode="multiple" to allow selecting multiple items. Use selectedKeys and onSelectionChange to control the selection state.

Sections

Aardvark
Cat
Dog
Kangaroo
Panda
Snake
Turtle
Lizard
"use client"

import React from "react"
import { Header, ListBoxSection } from "react-aria-components"

import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxSections() {
  return (
    <ListBox aria-label="Choose a pet" selectionMode="single" className="w-64">
      <ListBoxSection>
        <Header className="text-muted-foreground px-2 py-1 text-xs font-semibold">
          Mammals
        </Header>
        <ListBoxItem>Aardvark</ListBoxItem>
        <ListBoxItem>Cat</ListBoxItem>
        <ListBoxItem>Dog</ListBoxItem>
        <ListBoxItem>Kangaroo</ListBoxItem>
        <ListBoxItem>Panda</ListBoxItem>
      </ListBoxSection>
      <ListBoxSection>
        <Header className="text-muted-foreground px-2 py-1 text-xs font-semibold">
          Reptiles
        </Header>
        <ListBoxItem>Snake</ListBoxItem>
        <ListBoxItem>Turtle</ListBoxItem>
        <ListBoxItem>Lizard</ListBoxItem>
      </ListBoxSection>
    </ListBox>
  )
}
import { Header, ListBoxSection } from "react-aria-components"
import { ListBox, ListBoxItem } from "@/components/ui/list-box"
 
<ListBox aria-label="Choose a pet" selectionMode="single" className="w-64">
  <ListBoxSection>
    <Header className="px-2 py-1 text-xs font-semibold text-muted-foreground">
      Mammals
    </Header>
    <ListBoxItem>Aardvark</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Kangaroo</ListBoxItem>
    <ListBoxItem>Panda</ListBoxItem>
  </ListBoxSection>
  <ListBoxSection>
    <Header className="px-2 py-1 text-xs font-semibold text-muted-foreground">
      Reptiles
    </Header>
    <ListBoxItem>Snake</ListBoxItem>
    <ListBoxItem>Turtle</ListBoxItem>
    <ListBoxItem>Lizard</ListBoxItem>
  </ListBoxSection>
</ListBox>

Use ListBoxSection and Header to organize items into groups with section headers.

Disabled Items

Aardvark
Cat
Dog
Kangaroo
Panda
Snake
import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxDisabled() {
  return (
    <ListBox
      aria-label="Favorite animal"
      selectionMode="single"
      disabledKeys={["cat", "kangaroo"]}
      className="w-64"
    >
      <ListBoxItem id="aardvark">Aardvark</ListBoxItem>
      <ListBoxItem id="cat">Cat</ListBoxItem>
      <ListBoxItem id="dog">Dog</ListBoxItem>
      <ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
      <ListBoxItem id="panda">Panda</ListBoxItem>
      <ListBoxItem id="snake">Snake</ListBoxItem>
    </ListBox>
  )
}
<ListBox
  aria-label="Favorite animal"
  selectionMode="single"
  disabledKeys={["cat", "kangaroo"]}
  className="w-64"
>
  <ListBoxItem id="aardvark">Aardvark</ListBoxItem>
  <ListBoxItem id="cat">Cat</ListBoxItem>
  <ListBoxItem id="dog">Dog</ListBoxItem>
  <ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
  <ListBoxItem id="panda">Panda</ListBoxItem>
  <ListBoxItem id="snake">Snake</ListBoxItem>
</ListBox>

Use the disabledKeys prop to disable specific items.

Empty State

No results found

"use client"

import React from "react"

import { ListBox } from "@/components/ui/list-box"

export function ListBoxEmpty() {
  return (
    <ListBox
      aria-label="Search results"
      renderEmptyState={() => (
        <div className="flex min-h-[150px] items-center justify-center">
          <p className="text-muted-foreground text-sm">No results found</p>
        </div>
      )}
      className="w-64"
    >
      {[]}
    </ListBox>
  )
}
<ListBox
  aria-label="Search results"
  renderEmptyState={() => (
    <div className="flex min-h-[150px] items-center justify-center">
      <p className="text-muted-foreground text-sm">No results found</p>
    </div>
  )}
  className="w-64"
>
  {[]}
</ListBox>

Use renderEmptyState to display a custom message when the list is empty.

import Link from "next/link"

import { ListBox, ListBoxItem } from "@/components/ui/list-box"

export function ListBoxLinks() {
  return (
    <ListBox aria-label="Navigation" className="w-64">
      <ListBoxItem href="/docs" textValue="Documentation">
        <Link href="/docs">Documentation</Link>
      </ListBoxItem>
      <ListBoxItem href="/docs/components" textValue="Components">
        <Link href="/docs/components">Components</Link>
      </ListBoxItem>
      <ListBoxItem href="/examples" textValue="Examples">
        <Link href="/examples">Examples</Link>
      </ListBoxItem>
      <ListBoxItem href="/blocks" textValue="Blocks">
        <Link href="/blocks">Blocks</Link>
      </ListBoxItem>
    </ListBox>
  )
}
import Link from "next/link"
import { ListBox, ListBoxItem } from "@/components/ui/list-box"
 
<ListBox aria-label="Navigation" className="w-64">
  <ListBoxItem href="/docs" textValue="Documentation">
    <Link href="/docs">Documentation</Link>
  </ListBoxItem>
  <ListBoxItem href="/docs/components" textValue="Components">
    <Link href="/docs/components">Components</Link>
  </ListBoxItem>
  <ListBoxItem href="/examples" textValue="Examples">
    <Link href="/examples">Examples</Link>
  </ListBoxItem>
  <ListBoxItem href="/blocks" textValue="Blocks">
    <Link href="/blocks">Blocks</Link>
  </ListBoxItem>
</ListBox>

List items can contain links for navigation. Pass the href prop to ListBoxItem and wrap content with a Next.js Link.

Dynamic Collections

Aardvark
Cat
Dog
Kangaroo
Panda
Snake
"use client"

import { ListBox, ListBoxItem } from "@/components/ui/list-box"

interface Animal {
  id: string
  name: string
}

const animals: Animal[] = [
  { id: "aardvark", name: "Aardvark" },
  { id: "cat", name: "Cat" },
  { id: "dog", name: "Dog" },
  { id: "kangaroo", name: "Kangaroo" },
  { id: "panda", name: "Panda" },
  { id: "snake", name: "Snake" },
]

export function ListBoxDynamic() {
  return (
    <ListBox
      aria-label="Favorite animal"
      selectionMode="single"
      items={animals}
      className="w-64"
    >
      {(item) => <ListBoxItem id={item.id}>{item.name}</ListBoxItem>}
    </ListBox>
  )
}
"use client"
 
import { ListBox, ListBoxItem } from "@/components/ui/list-box"
 
interface Animal {
  id: string
  name: string
}
 
const animals: Animal[] = [
  { id: "aardvark", name: "Aardvark" },
  { id: "cat", name: "Cat" },
  { id: "dog", name: "Dog" },
  { id: "kangaroo", name: "Kangaroo" },
  { id: "panda", name: "Panda" },
  { id: "snake", name: "Snake" },
]
 
export default function Example() {
  return (
    <ListBox
      aria-label="Favorite animal"
      selectionMode="single"
      items={animals}
      className="w-64"
    >
      {(item) => <ListBoxItem id={item.id}>{item.name}</ListBoxItem>}
    </ListBox>
  )
}

Use the items prop with a render function to dynamically generate list items from data.

API Reference

ListBox

The ListBox component displays a list of items with support for selection and keyboard navigation.

PropTypeDefaultDescription
selectionMode"none" | "single" | "multiple""none"Whether and how selection is enabled.
selectedKeysIterable<Key>-The currently selected keys (controlled).
defaultSelectedKeysIterable<Key>-The initial selected keys (uncontrolled).
onSelectionChange(keys: Selection) => void-Handler called when the selection changes.
disabledKeysIterable<Key>-A list of keys for items that are disabled.
itemsIterable<T>-Item objects in the collection for dynamic rendering.
renderEmptyState() => React.ReactNode-Function to render when the list is empty.
aria-labelstring-An accessibility label for the listbox.

ListBoxItem

Individual items within a listbox.

PropTypeDefaultDescription
idKey-A unique key for the item (required for selection).
textValuestring-A string representation of the item for typeahead.
hrefstring-A URL to navigate to (makes the item a link).

Apart from the props above, the components also support all props from the react-aria-components library. Check the React Aria documentation for more details.

Accessibility

ListBoxes follow the ARIA listbox pattern. This provides support for:

  • Keyboard Navigation – Arrow keys, Home, End, Page Up/Down, and typeahead search
  • Selection – Space key selects/deselects items
  • Screen Readers – Proper ARIA attributes announce selection state and item count

Always provide an aria-label or aria-labelledby to identify the listbox:

<ListBox aria-label="Favorite animal">
  {/* items */}
</ListBox>
  • Select - For dropdown selections
  • ComboBox - For searchable dropdowns
  • GridList - For lists with row actions
  • Menu - For action menus