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.
listbox
popup using ARIA (combined with useListBox)<select>
elementA 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:
Name | Type | Description |
labelProps | HTMLAttributes<HTMLElement> | Props for the label element. |
triggerProps | HTMLAttributes<HTMLElement> & PressProps | Props for the popup trigger element. |
valueProps | HTMLAttributes<HTMLElement> | Props for the element representing the selected value. |
menuProps | HTMLAttributes<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 = ReactuseRef(); let { labelProps triggerProps valueProps menuProps } = useSelect({...props triggerRef} state); let {buttonProps} = useButton(triggerProps); return ( <div style={position: 'relative' display: 'inline-block'}> <div ...labelProps> propslabel</div> <HiddenSelect state= state triggerRef= triggerRef label= propslabel name= propsname /> <button ...buttonProps ref= triggerRef style={height: 30 fontSize: 14}> <span ...valueProps> stateselectedItem ? stateselectedItemrendered : 'Select an option' </span> <span aria-hidden="true" style={paddingLeft: 5}> ▼ </span> </button> stateisOpen && <ListBoxPopup ...menuProps state= state /> </div> ); } function ListBoxPopup({state ...otherProps}) { let ref = ReactuseRef(); let {listBoxProps} = useListBox({ ref autoFocus: statefocusStrategy disallowEmptySelection: true } state); let overlayRef = ReactuseRef(); let {overlayProps} = useOverlay({ ref: overlayRef onClose: () => stateclose() shouldCloseOnBlur: true isOpen: stateisOpen isDismissable: true }); return ( <FocusScope restoreFocus> <div ...overlayProps ref= overlayRef> <DismissButton onDismiss=() => stateclose() /> <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' }> [...statecollection]map(item => ( <Option key= itemkey item= item state= state /> )) </ul> <DismissButton onDismiss=() => stateclose() /> </div> </FocusScope> ) } function Option({item state}) { let ref = ReactuseRef(); let isDisabled = statedisabledKeyshas(itemkey); let isSelected = stateselectionManagerisSelected(itemkey); let {optionProps} = useOption({ key: itemkey ref isDisabled isSelected shouldSelectOnPressUp: true shouldFocusOnHover: true } state); let [isFocused setFocused] = ReactuseState(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' }> itemrendered </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.
Name | Type | Description |
triggerRef | RefObject<HTMLElement> | A ref to the trigger element. |
keyboardDelegate | KeyboardDelegate | An optional keyboard delegate implementation for type to select, to override the default. |
Method | Description |
getKeyBelow(key: Key): Key | Returns the key visually below the given one, or null for none. |
getKeyAbove(key: Key): Key | Returns the key visually above the given one, or null for none. |
getKeyLeftOf(key: Key): Key | Returns the key visually to the left of the given one, or null for none. |
getKeyRightOf(key: Key): Key | Returns the key visually to the right of the given one, or null for none. |
getKeyPageBelow(key: Key): Key | Returns the key visually one page below the given one, or null for none. |
getKeyPageAbove(key: Key): Key | Returns the key visually one page above the given one, or null for none. |
getFirstKey(key: Key, global: boolean): Key | Returns the first key, or null for none. |
getLastKey(key: Key, global: boolean): Key | Returns the last key, or null for none. |
getKeyForSearch(search: string, fromKey: Key): Key | Returns the next key after fromKey that matches the given search string, or null for none. |
Name | Type | Description |
selectedKey | Key | The key for the currently selected item. |
setSelectedKey | (key: Key) => void | Sets the selected key. |
selectedItem | Node<T> | The value of the currently selected item. |
isFocused | boolean | Whether the select is currently focused. |
setFocused | (isFocused: boolean) => void | Sets whether the select is focused. |
collection | Collection<Node<T>> | A collection of items in the list. |
disabledKeys | Set<Key> | A set of items that are disabled. |
selectionManager | SelectionManager | A selection manager to read and update multiple selection state. |
isOpen | boolean | Whether the menu is currently open. |
focusStrategy | FocusStrategy | Controls which item will be auto focused when the menu opens. |
Method | Description |
setOpen(value: boolean): void | Sets whether the menu is open. |
setFocusStrategy(value: FocusStrategy): void | Sets which item will be auto focused when the menu opens. |
open(): void | Opens the menu. |
close(): void | Closes the menu. |
toggle(focusStrategy: FocusStrategy | null): void | Toggles the menu. |
A generic interface to access a readonly sequential collection of unique keyed items.
Name | Type | Description |
size | number | The number of items in the collection. |
Method | Description |
getKeys(): Iterable<Key> | Iterate over all keys in the collection. |
getItem(key: Key): T | Get an item by its key. |
getKeyBefore(key: Key): Key | null | Get the key that comes before the given key in the collection. |
getKeyAfter(key: Key): Key | null | Get the key that comes after the given key in the collection. |
getFirstKey(): Key | null | Get the first key in the collection. |
getLastKey(): Key | null | Get the last key in the collection. |
An interface for reading and updating multiple selection state.
Name | Type | Description |
selectionMode | SelectionMode | The type of selection that is allowed in the collection. |
disallowEmptySelection | boolean | Whether the collection allows empty selection. |
isFocused | boolean | Whether the collection is currently focused. |
focusedKey | Key | The current focused key in the collection. |
selectedKeys | Set<Key> | The currently selected keys in the collection. |
isEmpty | any | Whether the selection is empty. |
isSelectAll | any | Whether all items in the collection are selected. |
Method | Description |
setFocused(isFocused: boolean): void | Sets whether the collection is focused. |
setFocusedKey(key: Key): void | Sets the focused key. |
isSelected(key: Key): void | Returns whether a key is selected. |
extendSelection(toKey: Key): void | Extends the selection to the given key. |
toggleSelection(key: Key): void | Toggles whether the given key is selected. |
replaceSelection(key: Key): void | Replaces the selection with only the given key. |
selectAll(): void | Selects all items in the collection. |
clearSelection(): void | Removes all keys from the selection. |
toggleSelectAll(): void | Toggles between select all and an empty selection. |
'none' | 'single' | 'multiple'
Name | Type | Description |
labelProps | HTMLAttributes<HTMLElement> | Props for the label element. |
triggerProps | HTMLAttributes<HTMLElement> & PressProps | Props for the popup trigger element. |
valueProps | HTMLAttributes<HTMLElement> | Props for the element representing the selected value. |
menuProps | HTMLAttributes<HTMLElement> | Props for the popup. |
Name | Type | Description |
isPressed | boolean | Whether the target is in a controlled press state (e.g. an overlay it triggers is open). |
isDisabled | boolean | Whether the press events should be disabled. |
onPress | (e: PressEvent) => void | Handler that is called when the press is released over the target. |
onPressStart | (e: PressEvent) => void | Handler that is called when a press interaction starts. |
onPressEnd | (e: PressEvent) => void | Handler that is called when a press interation ends, either over the target or when the pointer leaves the target. |
onPressChange | (isPressed: boolean) => void | Handler that is called when the press state changes. |
onPressUp | (e: PressEvent) => void | Handler that is called when a press is released over the target, regardless of whether it started on the target or not. |
Name | Type | Description |
type | 'pressstart' | 'pressend' | 'pressup' | 'press' | The type of press event being fired. |
pointerType | PointerType | The pointer type that triggered the press event. |
target | HTMLElement | The target element of the press event. |
shiftKey | boolean | Whether the shift keyboard modifier was held during the press event. |
ctrlKey | boolean | Whether the ctrl keyboard modifier was held during the press event. |
metaKey | boolean | Whether 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>
Name | Type | Description |
isOpen | boolean | Sets the open state of the menu |
defaultOpen | boolean | Sets the default open state of the menu |
onOpenChange | (isOpen: boolean) => void | Method that is called when the open state of the menu changes |
shouldFlip | boolean | Whether the menu should automatically flip direction when space is limited |
children | ReactElement<SectionProps<T>> | ReactElement<ItemProps<T>> | ReactElement<SectionProps<T>> | ReactElement<ItemProps<T>>[] | (item: T) => ReactElement<SectionProps<T>> | ReactElement<ItemProps<T>> | The contents of the collection. |
disabledKeys | Iterable<Key> | They item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. |
items | Iterable<T> | Item objects in the collection or section. |
itemKey | string | Property name on each item object to use as the unique key. id or key by default. |
isLoading | boolean | Whether the items are currently loading. |
onLoadMore | () => any | Handler that is called when more items should be loaded, e.g. while scrolling near the bottom. |
isDisabled | boolean | Whether the input is disabled. |
isRequired | boolean | Whether user input is required on the input before form submission. Often paired with the necessityIndicator prop to add a visual indicator to the input. |
validationState | ValidationState | Whether the input should display its "valid" or "invalid" visual styling. |
isReadOnly | boolean | Whether the input can be selected but not changed by the user. |
autoFocus | boolean | Whether the element should receive focus on render |
onFocus | (e: FocusEvent) => void | Handler that is called when the element receives focus. |
onBlur | (e: FocusEvent) => void | Handler that is called when the element loses focus. |
onFocusChange | (isFocused: boolean) => void | Handler that is called when the element's focus status changes. |
onKeyDown | (e: KeyboardEvent) => void | Handler that is called when a key is pressed. |
onKeyUp | (e: KeyboardEvent) => void | Handler that is called when a key is released. |
label | ReactNode | The content to display as the label. |
placeholder | string | Temporary text that occupies the text input when it is empty. |
disallowEmptySelection | boolean | Whether the collection allows empty selection. |
selectedKey | Key | The currently selected key in the collection (controlled). |
defaultSelectedKey | Key | The initial selected key in the collection (uncontrolled). |
onSelectionChange | (key: Key) => any | Handler that is called when the selection changes. |
Name | Type | Description |
title | ReactNode | Rendered contents of the section, e.g. a header. |
aria-label | string | An accessibility label for the section. |
children | ReactElement<ItemProps<T>> | ReactElement<ItemProps<T>>[] | (item: T) => ReactElement<ItemProps<T>> | Static child items or a function to render children. |
uniqueKey | Key | A unique key for the section. |
items | Iterable<T> | Item objects in the collection or section. |
itemKey | string | Property name on each item object to use as the unique key. id or key by default. |
isLoading | boolean | Whether the items are currently loading. |
onLoadMore | () => any | Handler that is called when more items should be loaded, e.g. while scrolling near the bottom. |
Name | Type | Description |
children | ReactNode | Rendered contents of the item or child items. |
title | ReactNode | Rendered contents of the item if children contains child items. |
textValue | string | A string representation of the item's contents, used for features like typeahead. |
aria-label | string | An accessibility label for this item. |
childItems | Iterable<T> | A list of child item objects. Used for dynamic collections. |
hasChildItems | boolean | Whether this item has children, even if not loaded yet. |
uniqueKey | Key | A 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.
Name | Type | Description |
state | SelectState<T> | State for the select. |
triggerRef | RefObject<HTMLElement> | A ref to the trigger element. |
label | ReactNode | The text label for the select. |
name | string | HTML 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
Name | Type | Description |
ref | RefObject<HTMLDivElement> | A ref to the listbox container element. |
isVirtualized | boolean | Whether the listbox uses virtual scrolling. |
keyboardDelegate | KeyboardDelegate | An optional keyboard delegate implementation for type to select, to override the default. |
autoFocus | boolean | FocusStrategy | Whether the auto focus the listbox or an option. |
shouldFocusWrap | boolean | Whether focus should wrap around when the end/start is reached. |
Name | Type | Description |
collection | Collection<Node<T>> | A collection of items in the list. |
disabledKeys | Set<Key> | A set of items that are disabled. |
selectionManager | SelectionManager | A selection manager to read and update multiple selection state. |
Name | Type | Description |
listBoxProps | HTMLAttributes<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
Name | Type | Description |
isDisabled | boolean | Whether the option is disabled. |
isSelected | boolean | Whether the option is selected. |
aria-label | string | A screen reader only label for the option. |
key | Key | The unique key for the option. |
ref | RefObject<HTMLElement> | A ref to the option element. |
shouldSelectOnPressUp | boolean | Whether selection should occur on press up instead of press down. |
shouldFocusOnHover | boolean | Whether the option should be focused when the user hovers over it. |
isVirtualized | boolean | Whether the option is contained in a virtual scrolling listbox. |
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. |
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.
Name | Type | Description |
children | ReactNode | The contents of the focus scope. |
contain | boolean | Whether to contain focus inside the scope, so users cannot move focus outside, for example in a modal dialog. |
restoreFocus | boolean | Whether to restore focus back to the element that was focused when the focus scope mounted, after the focus scope unmounts. |
autoFocus | boolean | Whether 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.
Name | Type | Description |
onDismiss | () => void | Called 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