{/* Copyright 2020 Adobe. All rights reserved. This file is licensed to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */}
A List
groups together related pieces of information so they are clearly associated with each other, easy to read, and navigable using the keyboard. The various items in the list are provided using the ListItem
component, which can have a icon, label or both.
List is the base component for the SelectList
and Menu
components.
The List
component implements the Listbox design pattern, per WAI-ARIA 1.1, which presents a list of options and allows a user to select one or more of them.
It should be noted that, in React Spectrum, List
does not provide for dynamic item selection when onSelect
is called on a ListItem
instance. The selected
state is a controlled prop on ListItem
. The SelectList
, Select
, and Menu
components implement dynamic item selection, and are more likely to be used as standalone components.
A listbox
that allows a single option to be chosen is a single-select listbox; one that allows multiple options to be selected is a multi-select listbox.
When screen readers present a listbox, they may render the name, state, and position of each option in the list. The name of an option is a string calculated by the browser, typically from the content of the option element. As a flat string, the name does not contain any semantic information. Thus, if an option contains a semantic element, such as a heading, screen reader users will not have access to the semantics. In addition, the interaction model conveyed by the listbox role to assistive technologies does not support interacting with elements inside of an option. Because of these traits of the listbox widget, it does not provide an accessible way to present a list of interactive elements, such as links, buttons, or checkboxes. To present a list of interactive elements, see the grid pattern.
Avoiding very long option names facilitates understandability and perceivability for screen reader users. The entire name of an option is spoken as a single unit of speech when the option is read. When too much information is spoken as the result of a single key press, it is difficult to understand. Long names inhibit perception by increasing the impact of interrupted speech because users typically have to re-read the entire option. And, if the user does not understand what is spoken, reading the name by character, word, or phrase may be a difficult operation for many screen reader users in the context of a listbox widget.
Sets of options where each option name starts with the same word or phrase can also significantly degrade usability for keyboard and screen reader users. Scrolling through the list to find a specific option becomes inordinately time consuming for a screen reader user who must listen to that word or phrase repeated before hearing what is unique about each option. For example, if a listbox for choosing a city were to contain options where each city name were preceded by a country name, and if many cities were listed for each country, a screen reader user would have to listen to the country name before hearing each city name. In such a scenario, it would be better to have 2 list boxes, one for country and one for city.
For a vertically oriented listbox:
- When a single-select listbox receives focus:
- If none of the options are selected before the listbox receives focus, the first option receives focus. Optionally, the first option may be automatically selected.
- If an option is selected before the listbox receives focus, focus is set on the selected option.
- When a multi-select listbox receives focus:
- If none of the options are selected before the listbox receives focus, focus is set on the first option and there is no automatic change in the selection state.
- If one or more options are selected before the listbox receives focus, focus is set on the first option in the list that is selected.
Down Arrow
: Moves focus to the next option. Optionally, in a single-select listbox, selection may also move with focus.Up Arrow
: Moves focus to the previous option. Optionally, in a single-select listbox, selection may also move with focus.Home
(Optional): Moves focus to first option. Optionally, in a single-select listbox, selection may also move with focus. Supporting this key is strongly recommended for lists with more than five options.End
(Optional): Moves focus to last option. Optionally, in a single-select listbox, selection may also move with focus. Supporting this key is strongly recommended for lists with more than five options.PageUp
(Optional): When the list scrolls, moves focus to the item one page before the item with focus, or if the list does not scroll, the first item. Optionally, in a single-select listbox, selection may also move with focus.PageDown
(Optional): When the list scrolls, moves focus to the item one page after the item with focus, or if the list does not scroll, the last item. Optionally, in a single-select listbox, selection may also move with focus.- Type-ahead is recommended for all listboxes, especially those with more than seven options:
- Type a character: focus moves to the next item with a name that starts with the typed character.
- Type multiple characters in rapid succession: focus moves to the next item with a name that starts with the string of characters typed.
- Multiple Selection: Authors may implement either of two interaction models to support multiple selection: a recommended model that does not require the user to hold a modifier key, such as
Shift
orControl
, while navigating the list or an alternative model that does require modifier keys to be held while navigating in order to avoid losing selection states.- Recommended selection model -- holding modifier keys is not necessary (React-Spectrum v2 does not currently implement keyboard combinations marked as "Optional", below):
Space
: changes the selection state of the focused option.Shift + Down Arrow
(Optional): Moves focus to and toggles the selected state of the next option.Shift + Up Arrow
(Optional): Moves focus to and toggles the selected state of the previous option.Shift + Space
(Optional): Selects contiguous items from the most recently selected item to the focused item.Control + Shift + Home
(Optional): Selects the focused option and all options up to the first option. Optionally, moves focus to the first option.Control + Shift + End
(Optional): Selects the focused option and all options down to the last option. Optionally, moves focus to the last option.Control + A
(Optional): Selects all options in the list. Optionally, if all options are selected, it may also unselect all options.
- Alternative selection model -- moving focus without holding a Shift or Control modifier unselects all selected nodes except the focused node (React-Spectrum v2 does not currently implement this alternative selection model):
Shift + Down Arrow
: Moves focus to and toggles the selection state of the next option.Shift + Up Arrow
: Moves focus to and toggles the selection state of the previous option.Control + Down Arrow
: Moves focus to the next option without changing its selection state.Control + Up Arrow
: Moves focus to the previous option without changing its selection state.Control + Space
Changes the selection state of the focused option.Shift + Space
(Optional): Selects contiguous items from the most recently selected item to the focused item.Control + Shift + Home
(Optional): Selects the focused option and all options up to the first option. Optionally, moves focus to the first option.Control + Shift + End
(Optional): Selects the focused option and all options down to the last option. Optionally, moves focus to the last option.Control + A
(Optional): Selects all options in the list. Optionally, if all options are selected, it may also unselect all options.
- Recommended selection model -- holding modifier keys is not necessary (React-Spectrum v2 does not currently implement keyboard combinations marked as "Optional", below):
- DOM focus (the active element) is functionally distinct from the selected state. For more details, see this description of differences between focus and selection.
- The
listbox
role supports thearia-activedescendant
property, which provides an alternative to moving DOM focus amongoption
elements when implementing keyboard navigation. For details, see Managing Focus in Composites Using aria-activedescendant. - In a single-select listbox, moving focus may optionally unselect the previously selected option and select the newly focused option. This model of selection is known as "selection follows focus". Having selection follow focus can be very helpful in some circumstances and can severely degrade accessibility in others. For additional guidance, see Deciding When to Make Selection Automatically Follow Focus.
- If selecting or unselecting all options is an important function, implementing separate controls for these actions, such as buttons for "Select All" and "Unselect All", significantly improves accessibility.
- If the options in a listbox are arranged horizontally:
ArrowDown
performs asArrowRight
is described above, and vice versa.ArrowUp
performs asArrowLeft
is described above, and vice versa.
- An element that contains or owns all the listbox options has role
listbox
. - Each option in the listbox has role
option
and is a DOM descendant of the element with rolelistbox
or is referenced by anaria-owns
property on the listbox element. - If the listbox is not part of another widget, then it has a visible label referenced by
aria-labelledby
on the element with rolelistbox
. - In a single-select listbox, the selected option has
aria-selected
set totrue
. - If the listbox supports multiple selection:
- The element with role
listbox
hasaria-multiselectable
set totrue
. - All selected options have
aria-selected
set totrue
. - All options that are not selected have
aria-selected
set tofalse
.
- The element with role
- If the complete set of available options is not present in the DOM due to dynamic loading as the user scrolls, their
aria-setsize
andaria-posinset
attributes are set appropriately. - If options are arranged horizontally, the element with role
listbox
hasaria-orientation
set tohorizontal
. The default value ofaria-orientation
forlistbox
isvertical
. - Options in a listbox may be divided into groups, like an
optgroup
in an HTMLselect
:- To define a labelled group, options should be contained within an element with the role of
group
. The group element should be labelled usingaria-label
or witharia-labelledby
referencing a visible text element heading, included as a child of the group, byid
. Since a listbox does not normally expect a text node or heading as a descendant, this visible text element heading should be removed from the accessibility tree as a standalone accessibility object usingaria-hidden
.
- To define a labelled group, options should be contained within an element with the role of
In React Spectrum, List
does not provide for dynamic item selection when onSelect
is called on a ListItem
instance. The selected
state is a controlled prop on ListItem
. The SelectList
, Select
, and Menu
components implement dynamic item selection, and are more likely to be used as standalone components.
Since List
is the base component for the Menu
component:
- The
List
component accepts rolemenu
in addition to rolelistbox
. - The
ListItem
component accepts rolemenuitem
,menuitemcheckbox
, andmenuitemradio
, in addition to roleoption
.
Keyboard navigation in List
is provided by the FocusManager
utility component with the following parameters:
itemSelector
equal to.spectrum-Menu-item:not(.is-disabled)
.selectedItemSelector
equal to.spectrum-Menu-item:not(.is-disabled).is-selected
.typeToSelect
defaults totrue
autoFocus
defaults tofalse
, but can be set totrue
when theList
is used in aPopover
as part of aSelect
orDropdownButton
.
FocusManager