ListBox

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

Theme 
Aardvark
Cat
Dog
Kangaroo
Panda
Snake
selectionMode 
Example
ListBox.tsx
ListBox.css
import {ListBox, ListBoxItem} from './ListBox';

<ListBox aria-label="Favorite animal" selectionMode="multiple">
  <ListBoxItem>Aardvark</ListBoxItem>
  <ListBoxItem>Cat</ListBoxItem>
  <ListBoxItem>Dog</ListBoxItem>
  <ListBoxItem>Kangaroo</ListBoxItem>
  <ListBoxItem>Panda</ListBoxItem>
  <ListBoxItem>Snake</ListBoxItem>
</ListBox>

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.

Aardvark
Cat
Dog
Kangaroo
Koala
Penguin
Snake
Turtle
Wombat
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.

ReadRead only
WriteRead and write only
AdminFull access
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>

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.

Lettuce
Tomato
Onion
Ham
Tuna
Tofu
Mayonaise
Mustard
Ranch
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>
  );
}

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.

selectionBehavior 
import {ListBox, ListBoxItem} from 'react-aria-components';

<ListBox aria-label="Links" selectionMode="multiple">
  <ListBoxItem href="https://adobe.com/" target="_blank">Adobe</ListBoxItem>
  <ListBoxItem href="https://apple.com/" target="_blank">Apple</ListBoxItem>
  <ListBoxItem href="https://google.com/" target="_blank">Google</ListBoxItem>
  <ListBoxItem href="https://microsoft.com/" target="_blank">Microsoft</ListBoxItem>
</ListBox>

Empty state

No results found.
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.

Lettuce
Tomato
Cheese
Tuna Salad
Egg Salad
Ham

Current selection: cheese

selectionMode 
selectionBehavior 
disallowEmptySelection 
import type {Selection} from 'react-aria-components';
import {ListBox, ListBoxItem} from 'react-aria-components';
import {useState} from 'react';

function Example(props) {
  let [selected, setSelected] = useState<Selection>(new Set(['cheese']));

  return (
    <div>
      <ListBox
        {...props}
        aria-label="Sandwich contents"
        selectionMode="multiple"
        selectedKeys={selected}
        onSelectionChange={setSelected}
      >
        <ListBoxItem id="lettuce">Lettuce</ListBoxItem>
        <ListBoxItem id="tomato">Tomato</ListBoxItem>
        <ListBoxItem id="cheese">Cheese</ListBoxItem>
        <ListBoxItem id="tuna" isDisabled>Tuna Salad</ListBoxItem>
        <ListBoxItem id="egg">Egg Salad</ListBoxItem>
        <ListBoxItem id="ham">Ham</ListBoxItem>
      </ListBox>
      <p>Current selection: {selected === 'all' ? 'all' : [...selected].join(', ')}</p>
    </div>
  );
}

Layouts

Use the layout and orientation props to create horizontal and vertical stacks and grids. This affects keyboard navigation and drag and drop behavior.

MercuryA year lasts 88 days
VenusSpins backwards!
EarthOnly planet with life
MarsHas the tallest volcano
JupiterCan fit 1,300 Earths
SaturnRings made of ice
UranusRolls on its side
NeptuneFastest winds in space
layout 
orientation 
import {ListBox, ListBoxItem, Text} from 'react-aria-components';

<ListBox aria-label="Planets" layout="grid" items={planets} selectionMode="multiple"> {item => ( <ListBoxItem textValue={item.title}> <Text slot="label">{item.title}</Text> <Text slot="description">{item.description}</Text> </ListBoxItem> )} </ListBox>

Drag and drop

ListBox supports drag and drop interactions when the dragAndDropHooks prop is provided using the 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.

Adobe Photoshop
Adobe XD
Adobe Dreamweaver
Adobe InDesign
Adobe Connect
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

Option 1Option 2ItemItem labelDescriptionDescriptionOption 3DescriptionItem descriptionSECTION TITLESection headerSection
<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.

NameTypeDefault
dragAndDropHooks<NoInfer<object>>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.
orientationDefault: 'vertical'
The primary orientation of the items. Usually this is the direction that the collection scrolls.
childrenReactNode(item: object) => ReactNodeDefault:
The contents of the collection.
itemsIterable<T>Default:
Item objects in the collection.
renderEmptyState(props: ) => ReactNodeDefault:
Provides content to display when there are no items in the list.
dependenciesReadonlyArray<any>Default:
Values that should invalidate the item cache when using dynamic collections.
selectionModeDefault:
The type of selection that is allowed in the collection.
selectionBehaviorDefault: "toggle"
How multiple selection should behave in the collection.
selectedKeys'all'Iterable<Key>Default:
The currently selected keys in the collection (controlled).
defaultSelectedKeys'all'Iterable<Key>Default:
The initial selected keys in the collection (uncontrolled).
onSelectionChange(keys: ) => voidDefault:
Handler that is called when the selection changes.
disabledKeysIterable<Key>Default:
The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.
disallowEmptySelectionbooleanDefault:
Whether the collection allows empty selection.
shouldSelectOnPressUpbooleanDefault:
Whether selection should occur on press up instead of press down.
shouldFocusWrapbooleanDefault:
Whether focus should wrap around when the end/start is reached.
shouldFocusOnHoverbooleanDefault:
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 PropCSS Selector
isEmptyCSS Selector: [data-empty]
Whether the listbox has no items and should display its empty state.
isFocusedCSS Selector: [data-focused]
Whether the listbox is currently focused.
isFocusVisibleCSS Selector: [data-focus-visible]
Whether the listbox is currently keyboard focused.
isDropTargetCSS Selector: [data-drop-target]
Whether the listbox is currently the active drop target.
layoutCSS Selector: [data-layout="stack | grid"]
Whether the items are arranged in a stack or grid.
stateCSS Selector:
State of the listbox.

ListBoxItem

A ListBoxItem represents an individual option in a ListBox.

NameType
idKey
The unique id of the item.
valueobject
The object value that this item represents. When using dynamic collections, this is set automatically.
textValuestring
A string representation of the item's contents, used for features like typeahead.
isDisabledboolean
Whether the item is disabled.
children<>
The children of the component. A function may be provided to alter the children based on component state.

Default className: react-aria-ListBoxItem

Render PropCSS Selector
isHoveredCSS Selector: [data-hovered]
Whether the item is currently hovered with a mouse.
isPressedCSS Selector: [data-pressed]
Whether the item is currently in a pressed state.
isSelectedCSS Selector: [data-selected]
Whether the item is currently selected.
isFocusedCSS Selector: [data-focused]
Whether the item is currently focused.
isFocusVisibleCSS Selector: [data-focus-visible]
Whether the item is currently keyboard focused.
isDisabledCSS 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.
selectionModeCSS Selector: [data-selection-mode="single | multiple"]
The type of selection that is allowed in the collection.
selectionBehaviorCSS Selector:
The selection behavior for the collection.

ListBoxSection

A ListBoxSection represents a section within a ListBox.

NameType
idKey
The unique id of the section.
valueobject
The object value that this section represents. When using dynamic collections, this is set automatically.
childrenReactNode(item: object) => ReactElement
Static child items or a function to render children.
itemsIterable<object>
Item objects in the section.
dependenciesReadonlyArray<any>
Values that should invalidate the item cache when using dynamic collections.

Default className: react-aria-ListBoxSection

ListBoxLoadMoreItem

NameTypeDefault
childrenReactNodeDefault:
The load more spinner to render when loading additional items.
isLoadingbooleanDefault:
Whether or not the loading spinner should be rendered or not.
scrollOffsetnumberDefault: 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() => anyDefault:
Handler that is called when more items should be loaded, e.g. while scrolling near the bottom.

Default className: react-aria-ListBoxLoadMoreItem