useSelect

Provides the behavior and accessibility implementation for a select component. A select displays a collapsible list of options and allows a user to select one of them.

useSelect<T>(props: SelectProps, state: SelectState<T>): SelectAria

A select can be built using the <select> and <option> HTML elements, but this is not possible to style consistently cross browser, especially the options. useSelect helps achieve accessible select components that can be styled as needed without compromising on high quality interactions.

  • Exposed to assistive technology as a button with a listbox popup using ARIA (combined with useListBox)
  • Support for selecting a single option
  • Support for disabled options
  • Support for sections
  • Labeling support for accessibility
  • Support for mouse, touch, and keyboard interactions
  • Tab stop focus management
  • Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly
  • Typeahead to allow selecting options by typing text, even without opening the listbox
  • Browser autofill integration via a hidden native <select> element
  • Support for mobile form navigation via software keyboard
  • Mobile screen reader listbox dismissal support

A select consists of a label, a button which displays a selected value, and a listbox, displayed in a popup. Users can click, touch, or use the keyboard on the button to open the listbox popup. useSelect handles exposing the correct ARIA attributes for accessibility and handles the interactions for the select in its collapsed state. It should be combined with useListBox, which handles the implementation of the popup listbox.

useSelect returns props that you should spread onto the appropriate element:

NameTypeDescription
labelPropsHTMLAttributes<HTMLElement>Props for the label element.
triggerPropsHTMLAttributes<HTMLElement> & PressPropsProps for the popup trigger element.
valuePropsHTMLAttributes<HTMLElement>Props for the element representing the selected value.
menuPropsHTMLAttributes<HTMLElement>Props for the popup.

State is managed by the useSelectState hook from @react-stately/select. The state object should be passed as an option to useSelect

If a select not have a visible label, an aria-label or aria-labelledby prop must be passed instead to identify it to assisitive technology.

useSelect requires knowledge of the options in the select 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 useSelectState from @react-stately/select implements a JSX based interface for building collections instead. See Collection Components for more information, and Collection Interface for internal details.

In addition, useSelectState 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. It also holds state to track if the popup is open. For more information about selection, see Selection.

This example uses a <button> element for the trigger, with a <span> inside to hold the value, and another for the dropdown arrow icon (hidden from screen readers with aria-hidden). A <HiddenSelect> is used to render a hidden native <select>, which enables browser form autofill support.

The listbox popup uses useListBox and useOption to render the list of options. In addition, a <FocusScope> is used to automatically restore focus to the trigger when the popup closes. A hidden <DismissButton> is added at the start and end of the popup to allow screen reader users to dismiss the popup.

This example does not do any advanced popover positioning or portaling to escape its visual container. See useOverlayTrigger for an example of how to implement this using useOverlayPosition.

In addition, see useListBox for examples of sections (option groups), and more complex options.

import {useSelectState} from '@react-stately/select'; import {Item} from '@react-stately/collections'; import {HiddenSelect} from '@react-aria/select'; import {useListBox, useOption} from '@react-aria/listbox'; import {mergeProps} from '@react-aria/utils'; import {useButton} from '@react-aria/button'; import {useFocus} from '@react-aria/interactions'; import {FocusScope} from '@react-aria/focus'; import {useOverlay, DismissButton} from '@react-aria/overlays'; function Select(props) { let state = useSelectState(props); let triggerRef = React.useRef(); let { labelProps, triggerProps, valueProps, menuProps } = useSelect({...props, triggerRef}, state); let {buttonProps} = useButton(triggerProps); return ( <div style={{position: 'relative', display: 'inline-block'}}> <div {...labelProps}>{props.label}</div> <HiddenSelect state={state} triggerRef={triggerRef} label={props.label} name={props.name} /> <button {...buttonProps} ref={triggerRef} style={{height: 30, fontSize: 14}}> <span {...valueProps}> {state.selectedItem ? state.selectedItem.rendered : 'Select an option' } </span> <span aria-hidden="true" style={{paddingLeft: 5}}></span> </button> {state.isOpen && <ListBoxPopup {...menuProps} state={state} /> } </div> ); } function ListBoxPopup({state, ...otherProps}) { let ref = React.useRef(); let {listBoxProps} = useListBox({ ref, autoFocus: state.focusStrategy, disallowEmptySelection: true }, state); let overlayRef = React.useRef(); let {overlayProps} = useOverlay({ ref: overlayRef, onClose: () => state.close(), shouldCloseOnBlur: true, isOpen: state.isOpen, isDismissable: true }); return ( <FocusScope restoreFocus> <div {...overlayProps} ref={overlayRef}> <DismissButton onDismiss={() => state.close()} /> <ul {...mergeProps(listBoxProps, otherProps)} ref={ref} style={{ position: 'absolute', width: '100%', margin: '4px 0 0 0', padding: 0, listStyle: 'none', border: '1px solid gray', background: 'lightgray' }}> {[...state.collection].map(item => ( <Option key={item.key} item={item} state={state} /> ))} </ul> <DismissButton onDismiss={() => state.close()} /> </div> </FocusScope> ) } function Option({item, state}) { let ref = React.useRef(); let isDisabled = state.disabledKeys.has(item.key); let isSelected = state.selectionManager.isSelected(item.key); let {optionProps} = useOption({ key: item.key, ref, isDisabled, isSelected, shouldSelectOnPressUp: true, shouldFocusOnHover: true }, state); let [isFocused, setFocused] = React.useState(false); let {focusProps} = useFocus({onFocusChange: setFocused}); return ( <li {...mergeProps(optionProps, focusProps)} ref={ref} style={{ background: isSelected ? 'blueviolet' : isFocused ? 'gray' : 'transparent', color: isSelected || isFocused ? 'white' : 'black', padding: '2px 5px', outline: 'none', cursor: 'pointer' }}> {item.rendered} </li> ); } <Select label="Favorite Color"> <Item>Red</Item> <Item>Orange</Item> <Item>Yellow</Item> <Item>Green</Item> <Item>Blue</Item> <Item>Purple</Item> </Select>

useSelect and useListBox handle 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 select.

In right-to-left languages, the select should be mirrored. The arrow should be on the left, and the selected value should be on the right. In addition, the content of list options should flip. Ensure that your CSS accounts for this.

NameTypeDescription
triggerRefRefObject<HTMLElement>A ref to the trigger element.
keyboardDelegateKeyboardDelegateAn optional keyboard delegate implementation for type to select, to override the default.
MethodDescription
getKeyBelow(key: Key): KeyReturns the key visually below the given one, or null for none.
getKeyAbove(key: Key): KeyReturns the key visually above the given one, or null for none.
getKeyLeftOf(key: Key): KeyReturns the key visually to the left of the given one, or null for none.
getKeyRightOf(key: Key): KeyReturns the key visually to the right of the given one, or null for none.
getKeyPageBelow(key: Key): KeyReturns the key visually one page below the given one, or null for none.
getKeyPageAbove(key: Key): KeyReturns the key visually one page above the given one, or null for none.
getFirstKey(key: Key, global: boolean): KeyReturns the first key, or null for none.
getLastKey(key: Key, global: boolean): KeyReturns the last key, or null for none.
getKeyForSearch(search: string, fromKey: Key): KeyReturns the next key after fromKey that matches the given search string, or null for none.

Properties

NameTypeDescription
selectedKeyKeyThe key for the currently selected item.
setSelectedKey(key: Key) => voidSets the selected key.
selectedItemNode<T>The value of the currently selected item.
isFocusedbooleanWhether the select is currently focused.
setFocused(isFocused: boolean) => voidSets whether the select is focused.
collectionCollection<Node<T>>A collection of items in the list.
disabledKeysSet<Key>A set of items that are disabled.
selectionManagerSelectionManagerA selection manager to read and update multiple selection state.
isOpenbooleanWhether the menu is currently open.
focusStrategyFocusStrategyControls which item will be auto focused when the menu opens.

Methods

MethodDescription
setOpen(value: boolean): voidSets whether the menu is open.
setFocusStrategy(value: FocusStrategy): voidSets which item will be auto focused when the menu opens.
open(): voidOpens the menu.
close(): voidCloses the menu.
toggle(focusStrategy: FocusStrategynull): voidToggles the menu.

A generic interface to access a readonly sequential collection of unique keyed items.

Properties

NameTypeDescription
sizenumberThe number of items in the collection.

Methods

MethodDescription
getKeys(): Iterable<Key>Iterate over all keys in the collection.
getItem(key: Key): TGet an item by its key.
getKeyBefore(key: Key): KeynullGet the key that comes before the given key in the collection.
getKeyAfter(key: Key): KeynullGet the key that comes after the given key in the collection.
getFirstKey(): KeynullGet the first key in the collection.
getLastKey(): KeynullGet the last key in the collection.

An interface for reading and updating multiple selection state.

Properties

NameTypeDescription
selectionModeSelectionModeThe type of selection that is allowed in the collection.
disallowEmptySelectionbooleanWhether the collection allows empty selection.
isFocusedbooleanWhether the collection is currently focused.
focusedKeyKeyThe current focused key in the collection.
selectedKeysSet<Key>The currently selected keys in the collection.
isEmptyanyWhether the selection is empty.
isSelectAllanyWhether all items in the collection are selected.

Methods

MethodDescription
setFocused(isFocused: boolean): voidSets whether the collection is focused.
setFocusedKey(key: Key): voidSets the focused key.
isSelected(key: Key): voidReturns whether a key is selected.
extendSelection(toKey: Key): voidExtends the selection to the given key.
toggleSelection(key: Key): voidToggles whether the given key is selected.
replaceSelection(key: Key): voidReplaces the selection with only the given key.
selectAll(): voidSelects all items in the collection.
clearSelection(): voidRemoves all keys from the selection.
toggleSelectAll(): voidToggles between select all and an empty selection.
'none''single''multiple'
NameTypeDescription
labelPropsHTMLAttributes<HTMLElement>Props for the label element.
triggerPropsHTMLAttributes<HTMLElement> & PressPropsProps for the popup trigger element.
valuePropsHTMLAttributes<HTMLElement>Props for the element representing the selected value.
menuPropsHTMLAttributes<HTMLElement>Props for the popup.
NameTypeDescription
isPressedbooleanWhether the target is in a controlled press state (e.g. an overlay it triggers is open).
isDisabledbooleanWhether the press events should be disabled.
onPress(e: PressEvent) => voidHandler that is called when the press is released over the target.
onPressStart(e: PressEvent) => voidHandler that is called when a press interaction starts.
onPressEnd(e: PressEvent) => voidHandler that is called when a press interation ends, either over the target or when the pointer leaves the target.
onPressChange(isPressed: boolean) => voidHandler that is called when the press state changes.
onPressUp(e: PressEvent) => voidHandler that is called when a press is released over the target, regardless of whether it started on the target or not.
NameTypeDescription
type'pressstart' | 'pressend' | 'pressup' | 'press'The type of press event being fired.
pointerTypePointerTypeThe pointer type that triggered the press event.
targetHTMLElementThe target element of the press event.
shiftKeybooleanWhether the shift keyboard modifier was held during the press event.
ctrlKeybooleanWhether the ctrl keyboard modifier was held during the press event.
metaKeybooleanWhether the meta keyboard modifier was held during the press event.
'mouse' | 'pen' | 'touch' | 'keyboard' | 'virtual'

Provides state management for a select component. Handles building a collection of items from props, handles the open state for the popup menu, and manages multiple selection state.

useSelectState<T>(props: SelectProps<T>): SelectState<T>
NameTypeDescription
isOpenbooleanSets the open state of the menu
defaultOpenbooleanSets the default open state of the menu
onOpenChange(isOpen: boolean) => voidMethod that is called when the open state of the menu changes
shouldFlipbooleanWhether the menu should automatically flip direction when space is limited
childrenReactElement<SectionProps<T>>ReactElement<ItemProps<T>>ReactElement<SectionProps<T>>ReactElement<ItemProps<T>>[](item: T) => ReactElement<SectionProps<T>>ReactElement<ItemProps<T>>The contents of the collection.
disabledKeysIterable<Key>They item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with.
itemsIterable<T>Item objects in the collection or section.
itemKeystringProperty name on each item object to use as the unique key. id or key by default.
isLoadingbooleanWhether the items are currently loading.
onLoadMore() => anyHandler that is called when more items should be loaded, e.g. while scrolling near the bottom.
isDisabledbooleanWhether the input is disabled.
isRequiredbooleanWhether user input is required on the input before form submission. Often paired with the necessityIndicator prop to add a visual indicator to the input.
validationStateValidationStateWhether the input should display its "valid" or "invalid" visual styling.
isReadOnlybooleanWhether the input can be selected but not changed by the user.
autoFocusbooleanWhether the element should receive focus on render
onFocus(e: FocusEvent) => voidHandler that is called when the element receives focus.
onBlur(e: FocusEvent) => voidHandler that is called when the element loses focus.
onFocusChange(isFocused: boolean) => voidHandler that is called when the element's focus status changes.
onKeyDown(e: KeyboardEvent) => voidHandler that is called when a key is pressed.
onKeyUp(e: KeyboardEvent) => voidHandler that is called when a key is released.
labelReactNodeThe content to display as the label.
placeholderstringTemporary text that occupies the text input when it is empty.
disallowEmptySelectionbooleanWhether the collection allows empty selection.
selectedKeyKeyThe currently selected key in the collection (controlled).
defaultSelectedKeyKeyThe initial selected key in the collection (uncontrolled).
onSelectionChange(key: Key) => anyHandler that is called when the selection changes.
NameTypeDescription
titleReactNodeRendered contents of the section, e.g. a header.
aria-labelstringAn accessibility label for the section.
childrenReactElement<ItemProps<T>>ReactElement<ItemProps<T>>[](item: T) => ReactElement<ItemProps<T>>Static child items or a function to render children.
uniqueKeyKeyA unique key for the section.
itemsIterable<T>Item objects in the collection or section.
itemKeystringProperty name on each item object to use as the unique key. id or key by default.
isLoadingbooleanWhether the items are currently loading.
onLoadMore() => anyHandler that is called when more items should be loaded, e.g. while scrolling near the bottom.
NameTypeDescription
childrenReactNodeRendered contents of the item or child items.
titleReactNodeRendered contents of the item if children contains child items.
textValuestringA string representation of the item's contents, used for features like typeahead.
aria-labelstringAn accessibility label for this item.
childItemsIterable<T>A list of child item objects. Used for dynamic collections.
hasChildItemsbooleanWhether this item has children, even if not loaded yet.
uniqueKeyKeyA unique key for this item.
'valid''invalid'T & {

stopPropagation: () => void,

continuePropagation: () => void

}

Renders a hidden native <select> element, which can be used to support browser form autofill, mobile form navigation, and native form submission.

NameTypeDescription
stateSelectState<T>State for the select.
triggerRefRefObject<HTMLElement>A ref to the trigger element.
labelReactNodeThe text label for the select.
namestringHTML form input name.

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.

useListBox<T>(props: AriaListBoxProps, state: ListState<T>): ListBoxAria
NameTypeDescription
refRefObject<HTMLDivElement>A ref to the listbox container element.
isVirtualizedbooleanWhether the listbox uses virtual scrolling.
keyboardDelegateKeyboardDelegateAn optional keyboard delegate implementation for type to select, to override the default.
autoFocusbooleanFocusStrategyWhether the auto focus the listbox or an option.
shouldFocusWrapbooleanWhether focus should wrap around when the end/start is reached.
NameTypeDescription
collectionCollection<Node<T>>A collection of items in the list.
disabledKeysSet<Key>A set of items that are disabled.
selectionManagerSelectionManagerA selection manager to read and update multiple selection state.
NameTypeDescription
listBoxPropsHTMLAttributes<HTMLElement>Props for the listbox element.

Provides the behavior and accessibility implementation for an option in a listbox. See useListBox for more details about listboxes.

useOption<T>(props: OptionProps, state: ListState<T>): OptionAria
NameTypeDescription
isDisabledbooleanWhether the option is disabled.
isSelectedbooleanWhether the option is selected.
aria-labelstringA screen reader only label for the option.
keyKeyThe unique key for the option.
refRefObject<HTMLElement>A ref to the option element.
shouldSelectOnPressUpbooleanWhether selection should occur on press up instead of press down.
shouldFocusOnHoverbooleanWhether the option should be focused when the user hovers over it.
isVirtualizedbooleanWhether the option is contained in a virtual scrolling listbox.
NameTypeDescription
optionPropsHTMLAttributes<HTMLElement>Props for the option element.
labelPropsHTMLAttributes<HTMLElement>Props for the main text element inside the option.
descriptionPropsHTMLAttributes<HTMLElement>Props for the description text element inside the option, if any.

A FocusScope manages focus for its descendants. It supports containing focus inside the scope, restoring focus to the previously focused element on unmount, and auto focusing children on mount. It also acts as a container for a programmatic focus management interface that can be used to move focus forward and back in response to user events.

NameTypeDescription
childrenReactNodeThe contents of the focus scope.
containbooleanWhether to contain focus inside the scope, so users cannot move focus outside, for example in a modal dialog.
restoreFocusbooleanWhether to restore focus back to the element that was focused when the focus scope mounted, after the focus scope unmounts.
autoFocusbooleanWhether to auto focus the first focusable element in the focus scope on mount.

A visually hidden button that can be used to allow screen reader users to dismiss a modal or popup when there is no visual affordance to do so.

NameTypeDescription
onDismiss() => voidCalled when the dismiss button is activated.

Handles positioning overlays like popovers and menus relative to a trigger element, and updating the position when the window resizes.

useOverlayPosition(props: AriaPositionProps): PositionAria'bottom' | 'bottom left' | 'bottom right' | 'bottom start' | 'bottom end' | 'top' | 'top left' | 'top right' | 'top start' | 'top end' | 'left' | 'left top' | 'left bottom' | 'start' | 'start top' | 'start bottom' | 'right' | 'right top' | 'right bottom' | 'end' | 'end top' | 'end bottom'Axis'center''top' | 'bottom' | 'left' | 'right'

ncG1vNJzZmiqlZawtb%2FPnpqtqqWie6O4zptlnKeimnu4tc2dprCrXqOytXvRnpicrKOlsqTA0a6kaG1gloSjrcBrmJ2cZZuFc66Ra2yebGVshnSwkGmabGhkbYSnrZVwaZ5nlKSwtHvRnpicrF2Wv6qtjq6qnouVobKkwI2hq6ak