A listbox displays a list of options and allows a user to select one or more of them.
Vanilla CSS theme
--tint CSS variable used by the Vanilla CSS examples.Content
ListBox follows the Collection Components API, accepting both static and dynamic collections. This example shows a dynamic collection, passing a list of objects to the items prop, and a function to render the children.
import {ListBox, ListBoxItem} from 'react-aria-components';
function Example() {
let options = [
{ id: 1, name: 'Aardvark' },
{ id: 2, name: 'Cat' },
{ id: 3, name: 'Dog' },
{ id: 4, name: 'Kangaroo' },
{ id: 5, name: 'Koala' },
{ id: 6, name: 'Penguin' },
{ id: 7, name: 'Snake' },
{ id: 8, name: 'Turtle' },
{ id: 9, name: 'Wombat' }
];
return (
<ListBox aria-label="Animals" items={options} selectionMode="single">
{(item) => <ListBoxItem>{item.name}</ListBoxItem>}
</ListBox>
);
}
Text slots
Use the "label" and "description" slots to separate primary and secondary content within a <ListBoxItem>. This improves screen reader announcements and can also be used for styling purposes.
import {ListBox, ListBoxItem, Text} from 'react-aria-components';
<ListBox aria-label="Permissions" selectionMode="single">
<ListBoxItem textValue="Read">
<Text slot="label">Read</Text>
<Text slot="description">Read only</Text>
</ListBoxItem>
<ListBoxItem textValue="Write">
<Text slot="label">Write</Text>
<Text slot="description">Read and write only</Text>
</ListBoxItem>
<ListBoxItem textValue="Admin">
<Text slot="label">Admin</Text>
<Text slot="description">Full access</Text>
</ListBoxItem>
</ListBox>
Accessibility warning
Sections
Use the <ListBoxSection> component to group options. A <Header> element may also be included to label the section. Sections without a header must have an aria-label.
import {ListBox, ListBoxItem, ListBoxSection, Header} from 'react-aria-components';
<ListBox aria-label="Sandwich contents" selectionMode="multiple">
<ListBoxSection>
<Header>Veggies</Header>
<ListBoxItem id="lettuce">Lettuce</ListBoxItem>
<ListBoxItem id="tomato">Tomato</ListBoxItem>
<ListBoxItem id="onion">Onion</ListBoxItem>
</ListBoxSection>
<ListBoxSection>
<Header>Protein</Header>
<ListBoxItem id="ham">Ham</ListBoxItem>
<ListBoxItem id="tuna">Tuna</ListBoxItem>
<ListBoxItem id="tofu">Tofu</ListBoxItem>
</ListBoxSection>
<ListBoxSection>
<Header>Condiments</Header>
<ListBoxItem id="mayo">Mayonaise</ListBoxItem>
<ListBoxItem id="mustard">Mustard</ListBoxItem>
<ListBoxItem id="ranch">Ranch</ListBoxItem>
</ListBoxSection>
</ListBox>
Asynchronous loading
Use renderEmptyState to display a spinner during initial load. To enable infinite scrolling, render a <ListBoxLoadMoreItem> at the end of the list or section. Use whatever data fetching library you prefer – this example uses useAsyncList from react-stately.
import {ListBox, ListBoxItem, ListBoxLoadMoreItem} from './ListBox';
import {ProgressCircle} from './ProgressCircle';
import {Collection, useAsyncList} from 'react-aria-components';
interface Character {
name: string
}
function AsyncLoadingExample() {
let list = useAsyncList<Character>({
async load({signal, cursor}) {
let res = await fetch(
cursor || `https://pokeapi.co/api/v2/pokemon`,
{ signal }
);
let json = await res.json();
return {
items: json.results,
cursor: json.next
};
}
});
return (
<ListBox
aria-label="Pick a Pokemon"
selectionMode="single"
renderEmptyState={() => (
<ProgressCircle isIndeterminate aria-label="Loading..." />
)}>
<Collection items={list.items}>
{(item) => <ListBoxItem id={item.name}>{item.name}</ListBoxItem>}
</Collection>
<ListBoxLoadMoreItem
onLoadMore={list.loadMore}
isLoading={list.loadingState === 'loadingMore'} />
</ListBox>
);
}
Links
Use the href prop on a <ListBoxItem> to create a link. See the framework setup guide to learn how to integrate with your framework.
By default, link items in a ListBox are not selectable, and only perform navigation when the user interacts with them. However, with selectionBehavior="replace", items will be selected when single clicking or pressing the Space key, and navigate to the link when double clicking or pressing the Enter key.
Empty state
import {ListBox} from 'react-aria-components';
<ListBox
aria-label="Search results"
renderEmptyState={() => 'No results found.'}>
{[]}
</ListBox>
Selection
Use the selectionMode prop to enable single or multiple selection. The selected items can be controlled via the selectedKeys prop, matching the id prop of the items. Items can be disabled with the isDisabled prop. See the selection guide for more details.
Current selection: cheese
Layouts
Use the layout and orientation props to create horizontal and vertical stacks and grids. This affects keyboard navigation and drag and drop behavior.
Drag and drop
ListBox supports drag and drop interactions when the dragAndDropHooks prop is provided using the useDragAndDrop hook. Users can drop data on the list as a whole, on individual items, insert new items between existing ones, or reorder items. React Aria supports drag and drop via mouse, touch, keyboard, and screen reader interactions. See the drag and drop guide to learn more.
import {ListBox, ListBoxItem, useDragAndDrop, useListData} from 'react-aria-components';
function Example() {
let list = useListData({
initialItems: [
{id: 1, name: 'Adobe Photoshop'},
{id: 2, name: 'Adobe XD'},
{id: 3, name: 'Adobe Dreamweaver'},
{id: 4, name: 'Adobe InDesign'},
{id: 5, name: 'Adobe Connect'}
]
});
let {dragAndDropHooks} = useDragAndDrop({
getItems: (keys, items: typeof list.items) => items.map(item => ({'text/plain': item.name})),
onReorder(e) {
if (e.target.dropPosition === 'before') {
list.moveBefore(e.target.key, e.keys);
} else if (e.target.dropPosition === 'after') {
list.moveAfter(e.target.key, e.keys);
}
}
});
return (
<ListBox
aria-label="Reorderable list"
selectionMode="multiple"
items={list.items}
dragAndDropHooks={dragAndDropHooks}
>
{item => <ListBoxItem>{item.name}</ListBoxItem>}
</ListBox>
);
}
Examples
API
<ListBox>
<ListBoxItem>
<Text slot="label" />
<Text slot="description" />
<SelectionIndicator />
</ListBoxItem>
<ListBoxSection>
<Header />
<ListBoxItem />
</ListBoxSection>
<ListBoxLoadMoreItem />
</ListBox>
ListBox
A listbox displays a list of options and allows a user to select one or more of them.
| Name | Type | Default |
|---|---|---|
dragAndDropHooks | DragAndDropHooks | Default: — |
The drag and drop hooks returned by useDragAndDrop used to enable drag and drop behavior for the ListBox. | ||
layout | 'stack' | 'grid' | Default: 'stack'
|
| Whether the items are arranged in a stack or grid. | ||
orientation | Orientation | Default: 'vertical'
|
| The primary orientation of the items. Usually this is the direction that the collection scrolls. | ||
children | ReactNode | | Default: — |
| The contents of the collection. | ||
items | Iterable | Default: — |
| Item objects in the collection. | ||
renderEmptyState | | Default: — |
| Provides content to display when there are no items in the list. | ||
dependencies | ReadonlyArray | Default: — |
| Values that should invalidate the item cache when using dynamic collections. | ||
selectionMode | SelectionMode | Default: — |
| The type of selection that is allowed in the collection. | ||
selectionBehavior | SelectionBehavior | Default: "toggle"
|
| How multiple selection should behave in the collection. | ||
selectedKeys | 'all' | Iterable | Default: — |
| The currently selected keys in the collection (controlled). | ||
defaultSelectedKeys | 'all' | Iterable | Default: — |
| The initial selected keys in the collection (uncontrolled). | ||
onSelectionChange | | Default: — |
| Handler that is called when the selection changes. | ||
disabledKeys | Iterable | Default: — |
| The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | ||
disallowEmptySelection | boolean | Default: — |
| Whether the collection allows empty selection. | ||
shouldSelectOnPressUp | boolean | Default: — |
| Whether selection should occur on press up instead of press down. | ||
shouldFocusWrap | boolean | Default: — |
| Whether focus should wrap around when the end/start is reached. | ||
shouldFocusOnHover | boolean | Default: — |
| Whether options should be focused when the user hovers over them. | ||
escapeKeyBehavior | 'clearSelection' | 'none' | Default: 'clearSelection'
|
| Whether pressing the escape key should clear selection in the listbox or not. Most experiences should not modify this option as it eliminates a keyboard user's ability to easily clear selection. Only use if the escape key is being handled externally or should not trigger selection clearing contextually. | ||
Default className: react-aria-ListBox
| Render Prop | CSS Selector |
|---|---|
isEmpty | CSS Selector: [data-empty]
|
| Whether the listbox has no items and should display its empty state. | |
isFocused | CSS Selector: [data-focused]
|
| Whether the listbox is currently focused. | |
isFocusVisible | CSS Selector: [data-focus-visible]
|
| Whether the listbox is currently keyboard focused. | |
isDropTarget | CSS Selector: [data-drop-target]
|
| Whether the listbox is currently the active drop target. | |
layout | CSS Selector: [data-layout="stack | grid"]
|
| Whether the items are arranged in a stack or grid. | |
state | CSS Selector: — |
| State of the listbox. | |
ListBoxItem
A ListBoxItem represents an individual option in a ListBox.
| Name | Type | |
|---|---|---|
id | Key | |
| The unique id of the item. | ||
value | object | |
| The object value that this item represents. When using dynamic collections, this is set automatically. | ||
textValue | string | |
| A string representation of the item's contents, used for features like typeahead. | ||
isDisabled | boolean | |
| Whether the item is disabled. | ||
children | ChildrenOrFunction | |
| The children of the component. A function may be provided to alter the children based on component state. | ||
Default className: react-aria-ListBoxItem
| Render Prop | CSS Selector |
|---|---|
isHovered | CSS Selector: [data-hovered]
|
| Whether the item is currently hovered with a mouse. | |
isPressed | CSS Selector: [data-pressed]
|
| Whether the item is currently in a pressed state. | |
isSelected | CSS Selector: [data-selected]
|
| Whether the item is currently selected. | |
isFocused | CSS Selector: [data-focused]
|
| Whether the item is currently focused. | |
isFocusVisible | CSS Selector: [data-focus-visible]
|
| Whether the item is currently keyboard focused. | |
isDisabled | CSS Selector: [data-disabled]
|
Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may
not be focused. Dependent on disabledKeys and disabledBehavior. | |
selectionMode | CSS Selector: [data-selection-mode="single | multiple"]
|
| The type of selection that is allowed in the collection. | |
selectionBehavior | CSS Selector: — |
| The selection behavior for the collection. | |
ListBoxSection
A ListBoxSection represents a section within a ListBox.
| Name | Type | |
|---|---|---|
id | Key | |
| The unique id of the section. | ||
value | object | |
| The object value that this section represents. When using dynamic collections, this is set automatically. | ||
children | ReactNode | | |
| Static child items or a function to render children. | ||
items | Iterable | |
| Item objects in the section. | ||
dependencies | ReadonlyArray | |
| Values that should invalidate the item cache when using dynamic collections. | ||
Default className: react-aria-ListBoxSection
ListBoxLoadMoreItem
| Name | Type | Default |
|---|---|---|
children | ReactNode | Default: — |
| The load more spinner to render when loading additional items. | ||
isLoading | boolean | Default: — |
| Whether or not the loading spinner should be rendered or not. | ||
scrollOffset | number | Default: 1
|
| The amount of offset from the bottom of your scrollable region that should trigger load more. Uses a percentage value relative to the scroll body's client height. Load more is then triggered when your current scroll position's distance from the bottom of the currently loaded list of items is less than or equal to the provided value. (e.g. 1 = 100% of the scroll region's height). | ||
onLoadMore | | Default: — |
| Handler that is called when more items should be loaded, e.g. while scrolling near the bottom. | ||
Default className: react-aria-ListBoxLoadMoreItem