Navigation
List Box
A keyboard-friendly list for selecting an item.
When to use it: Use it for choice lists that are not necessarily a form select.
Example
Selected: mint
import { useState } from "react";
import { ListBox, ListBoxItem, ListBoxSection, ListBoxSeparator } from "@comp0/react";
export function Example() {
const [value, setValue] = useState("mint");
return (
<div className="flex max-w-xs flex-col gap-2">
<ListBox
aria-label="Flavor"
className="rounded border border-zinc-950/10 p-1 dark:border-white/10"
value={value}
onChange={setValue}
>
<ListBoxSection aria-label="Fresh" className="grid gap-1">
<ListBoxItem
className="cursor-pointer rounded px-3 py-2.5 text-base text-zinc-800 data-selected:bg-teal-100 data-selected:text-teal-950 focus-visible:bg-teal-200 data-selected:focus-visible:bg-teal-200 focus-visible:outline-2 focus-visible:outline-teal-600 sm:py-2 sm:text-sm dark:text-zinc-100 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50 dark:focus-visible:bg-teal-800 dark:data-selected:focus-visible:bg-teal-800 dark:focus-visible:outline-teal-400"
value="mint"
>
Mint
</ListBoxItem>
<ListBoxItem
className="cursor-pointer rounded px-3 py-2.5 text-base text-zinc-800 data-selected:bg-teal-100 data-selected:text-teal-950 focus-visible:bg-teal-200 data-selected:focus-visible:bg-teal-200 focus-visible:outline-2 focus-visible:outline-teal-600 sm:py-2 sm:text-sm dark:text-zinc-100 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50 dark:focus-visible:bg-teal-800 dark:data-selected:focus-visible:bg-teal-800 dark:focus-visible:outline-teal-400"
value="basil"
>
Basil
</ListBoxItem>
</ListBoxSection>
<ListBoxSeparator className="my-1 h-px bg-zinc-950/10 dark:bg-white/10" />
<ListBoxSection aria-label="Sweet" className="grid gap-1">
<ListBoxItem
className="cursor-pointer rounded px-3 py-2.5 text-base text-zinc-800 data-selected:bg-teal-100 data-selected:text-teal-950 focus-visible:bg-teal-200 data-selected:focus-visible:bg-teal-200 focus-visible:outline-2 focus-visible:outline-teal-600 sm:py-2 sm:text-sm dark:text-zinc-100 dark:data-selected:bg-teal-950 dark:data-selected:text-teal-50 dark:focus-visible:bg-teal-800 dark:data-selected:focus-visible:bg-teal-800 dark:focus-visible:outline-teal-400"
value="plum"
>
Plum
</ListBoxItem>
</ListBoxSection>
</ListBox>
<p className="text-base text-zinc-600 sm:text-sm dark:text-zinc-400">Selected: {value}</p>
</div>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
ListBox
Selectable list container. Owns a DOM element.
ListBoxSectionOptional
Optional labelled section. Owns a DOM element.
ListBoxSeparatorOptional
Rule between groups of options. Owns a DOM element.
ListBoxItem
Selectable option. Owns a DOM element.
Step by step
- 1
Add the main part
Start ListBox with an aria-label.
- 2
Add the supporting parts
Add ListBoxItem for each selectable item.
- 3
Make the behavior clear
Use ListBoxSection when a long list needs labelled groups.
Exampletsx <ListBox aria-label="Color"><ListBoxItem value="red">Red</ListBoxItem></ListBox>
Keyboard
- ↓
- Moves active item down.
- ↑
- Moves active item up.
- ↵
- Selects the active item.
- Space
- Selects the active item.
Forms and accessibility
No native form behavior by itself.
Accessibility checklist
- Give the list an aria-label when it has no visible heading.
- Keep the focused option visibly distinct from selected state.
- Do not put buttons or links inside an option.
API reference
import { ListBox, ListBoxItem, ListBoxSection, ListBoxSeparator } from "@comp0/react";ListBox
DOM elementSelectable list container.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Names the list; nothing labels it automatically. |
value | string | Controlled selection. |
defaultValue | string | Initial selection. |
onChange | (value: string) => void | Receives the next selection. |
orientation | "vertical" | "horizontal" | Arrow-key axis. |
ListBoxSection
OptionalDOM elementOptional labelled section.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Names the group of options. |
ListBoxSeparator
OptionalDOM elementRule between groups of options.
ListBoxItem
DOM elementSelectable option.
| Prop | Type | Description |
|---|---|---|
value | string | This option’s selection key. |
disabled | boolean | Disables the option. |
textValue | string | Overrides the text crawled from children when markup makes it ambiguous. |
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
[data-selected]on ListBoxItem
- The item is selected.
:focus-visibleon ListBoxItem
- The item has visible keyboard focus.
[data-disabled]on ListBoxItem
- The item is disabled.