useListBox
Provides the behavior and accessibility implementation for a listbox component. A listbox displays a list of options and allows a user to select one or more of them.
| install | yarn add @react-aria/listbox |
|---|---|
| version | 3.4.4 |
| usage | import {useListBox, useOption, useListBoxSection} from '@react-aria/listbox' |
API#
useListBox<T>(
props: AriaListBoxOptions<T>,
state: ListState<T>,
ref: RefObject<HTMLElement>
): ListBoxAria
useOption<T>(
props: AriaOptionProps,
state: ListState<T>,
ref: RefObject<HTMLElement>
): OptionAria
useListBoxSection(
(props: AriaListBoxSectionProps
)): ListBoxSectionAria
Features#
A listbox can be built using the <select>
and <option> HTML elements, but this is
not possible to style consistently cross browser. useListBox helps achieve accessible
listbox components that can be styled as needed.
Note: useListBox only handles the list itself. For a dropdown similar to a <select>, see useSelect.
- Exposed to assistive technology as a
listboxusing ARIA - Support for single, multiple, or no selection
- Support for disabled items
- Support for sections
- Labeling support for accessibility
- Support for mouse, touch, and keyboard interactions
- Tab stop focus management
- Keyboard navigation support including arrow keys, home/end, page up/down, select all, and clear
- Automatic scrolling support during keyboard navigation
- Typeahead to allow focusing options by typing text
- Virtualized scrolling support for performance with long lists
Anatomy#
A listbox consists of a container element, with a list of options or groups inside.
useListBox, useOption, and useListBoxSection handle exposing this to assistive
technology using ARIA, along with handling keyboard, mouse, and interactions to support
selection and focus behavior.
useListBox returns props that you should spread onto the list container element,
along with props for an optional visual label:
| Name | Type | Description |
listBoxProps | HTMLAttributes<HTMLElement> | Props for the listbox element. |
labelProps | HTMLAttributes<HTMLElement> | Props for the listbox's visual label element (if any). |
useOption returns props for an individual option and its children, along with states you can use for styling:
| Name | Type | Description |
optionProps | HTMLAttributes<HTMLElement> | Props for the option element. |
labelProps | HTMLAttributes<HTMLElement> | Props for the main text element inside the option. |
descriptionProps | HTMLAttributes<HTMLElement> | Props for the description text element inside the option, if any. |
isFocused | boolean | Whether the option is currently focused. |
isSelected | boolean | Whether the option is currently selected. |
isPressed | boolean | Whether the option is currently in a pressed state. |
isDisabled | boolean | Whether the option is disabled. |
useListBoxSection returns props for a section:
| Name | Type | Description |
itemProps | HTMLAttributes<HTMLElement> | Props for the wrapper list item. |
headingProps | HTMLAttributes<HTMLElement> | Props for the heading element, if any. |
groupProps | HTMLAttributes<HTMLElement> | Props for the group element. |
State is managed by the useListState
hook from @react-stately/list. The state object should be passed as an option to
each of the above hooks.
If a listbox, options, or group does not have a visible label, an aria-label or aria-labelledby
prop must be passed instead to identify the element to assistive technology.
State management#
useListBox requires knowledge of the options in the listbox in order to handle keyboard
navigation and other interactions. It does this using
the Collection
interface, which is a generic interface to access sequential unique keyed data. You can
implement this interface yourself, e.g. by using a prop to pass a list of item objects,
but useListState from
@react-stately/list implements a JSX based interface for building collections instead.
See Collection Components for more information,
and Collection Interface for internal details.
In addition, useListState
manages the state necessary for multiple selection and exposes
a SelectionManager,
which makes use of the collection to provide an interface to update the selection state.
For more information, see Selection.
Example#
This example uses HTML <ul> and <li> elements to represent the list, and applies
props from useListBox
and useOption.
Sections#
This example shows how a listbox can support sections with separators and headings
using props from useListBoxSection.
This is accomplished using four extra elements: an <li> between the sections to
represent the separator, an <li> to contain the heading <span> element, and a
<ul> to contain the child items. This structure is necessary to ensure HTML semantics
are correct.
Complex options#
By default, options that only contain text will be labeled by the contents of the option.
For options that have more complex content (e.g. icons, multiple lines of text, etc.), use
labelProps and descriptionProps from useOption
as needed to apply to the main text element of the option and its description. This improves screen
reader announcement.
NOTE: listbox options cannot contain interactive content (e.g. buttons, checkboxes, etc.).
For these cases, see useGrid instead.
This example shows how labelProps and descriptionProps can be applied to child elements of
the item to apply ARIA properties returned by useOption.
This is done using React.cloneElement in this example, but you can use context or other
approaches for this as well.
Internationalization#
useListBox handles some aspects of internationalization automatically.
For example, type to select is implemented with an
Intl.Collator
for internationalized string matching. You are responsible for localizing all labels and option
content that is passed into the listbox.
RTL#
In right-to-left languages, the listbox options should be mirrored. The text content should be aligned to the right. Ensure that your CSS accounts for this.