# Listbox

> A visible set of options from which people choose one or several.

A listbox presents a set of options from which people choose one or several. The
options remain visible, so the range of choices and the current choice are
apparent at a glance.

## When to use

Use a listbox when seeing the options informs the choice, or when people choose
several. When space is limited and only the result matters, a popup button or a
menu conserves room. For a choice among a few options, radio buttons or a
segmented control are more direct.

## Best practices

**Name the list.** Every listbox needs an accessible name that says what is being
chosen, even where a visible heading makes it evident.

**Order options meaningfully** — alphabetically, by recency or by frequency — and
keep the order stable while people are choosing.

**Begin each label with the word that distinguishes it.** People scan the start
of a label, and typeahead matches from it.

**Group related options** under short headings when a list is long or its options
fall into kinds. Groups remain one sequence: the arrow keys pass from one group
to the next.

**Show the extent of a multiple selection** when the list scrolls. A count beside
the list keeps selected options that are out of view from being forgotten.

**Prefer disabling to removing** an option that is temporarily unavailable, when
its presence helps people understand what the list offers.

**Distinguish choosing from acting.** Selecting an option chooses it. Opening it
or carrying out its action is separate: Return (Enter) or a double click. A key
held down acts once.

**Keep what was selected.** An option that is selected but unavailable, or not
shown at the moment, stays selected while others are chosen around it.

**Keep focus in the list.** When the option that has focus goes away — removed,
or made unavailable — focus moves to the option that takes its place, not out of
the list.

**Say when there is nothing to choose.** A list with no options — filtered to
nothing, or not yet filled — shows a short statement of that in their place, and
gives it as the list's description, so that it is heard when the list takes
focus. The statement is words, not controls.

**Give each option its own value.** Options that share a value are selected
together and cannot be told apart; the arrow keys still pass through each.

**Stay immediate however long the list.** With thousands of options, a key press
changes only the options it concerns: the one focus left, the one it reached,
those whose selection changed. Reading every option's text, or drawing every
option again, on each key is felt long before the list is long.

## Platform considerations

**Pointer and keyboard.** A listbox follows the conventions of
[Selection](https://ui.publictheta.com/foundations/selection.md), [Keyboard navigation](https://ui.publictheta.com/foundations/navigation.md)
and [Typeahead](https://ui.publictheta.com/foundations/typeahead.md). Page Up and Page Down move by as many
options as the list shows at once, along whichever way the list runs. A query
being typed ends when focus leaves the list.

**Dragging.** In a multiple selection, a press on an option that is not selected,
dragged with a mouse or a pen, selects the range it passes over. The drag goes on
when the pointer leaves the list, and the list scrolls while the pointer is held
past its edge. A drag that begins on a selected option selects nothing: that
drag belongs to the selection, to carry it elsewhere.

**In a popup.** A list opened from a button highlights the option under the
pointer, chooses on release — so that a press which opened the popup can be
carried to an option — and opens each time on what is chosen.

**Touch.** Each option is at least 44 CSS pixels tall. A drag scrolls. In a
multiple selection a tap adds or removes an option, since touch provides no
modifier keys, and a long press adds the option under the finger; while the
finger stays down, moving it selects the range it passes over and the list does
not scroll. In a single selection a long press is a secondary press: it selects
the option and asks for its contextual menu. The platform's own callout and text
selection do not appear over an option.

**Acting by touch.** There is no double tap. Where options have an action, a tap
performs it wherever selecting would change nothing: on the selected option of a
single selection; and, in a multiple selection that replaces, while nothing is
selected — there a long press begins the selection, taps then add to and remove
from it, and when it is empty again a tap acts once more. A multiple selection
that toggles has no action by touch: give each option its own control for it.

**Pen.** A pen selects nothing as it presses, since its press may become a
scroll; its tap adds or removes like a finger's, and its drag selects a range
like a mouse's, adding to what was selected. Where the platform scrolls with the
pen instead, the selection is left as it was.

**Right-to-left.** In a horizontal listbox, the arrow keys follow the reading
direction.

**Assistive technology.** An option answers being activated by assistive
technology, which presses nothing. Expose the list as a listbox with its name, each option
with its selected and disabled state, and each group with its heading as its
name. A listbox that allows several selections says so.

## Behaviour

Each statement is verified by a test in Chromium, Chromium (touch), Firefox, WebKit, WebKit (touch), unless it names the environments it applies to or is marked open.

### Semantics

- Is a listbox of options, named by its label.
- States whether more than one option can be selected.
- Every option states whether it is selected.
- A disabled option says so.
- A group is exposed as a group, named by its label.
- On a touchscreen, every option is at least 44 pixels tall. *(Chromium (touch), WebKit (touch))*
- A list with no options says what it was given to say of that, as its description.
- Has no accessibility violations, in either selection mode.

### Focus

- Is a single stop in the tab sequence.
- Tab enters on the first selected option.
- Tab enters on the first enabled option when nothing is selected.
- Returning to the list returns to the option last focused.
- When the option holding the tab stop goes away, another takes it.
- When the option that has focus goes away, focus stays in the list.
- An empty list is still reachable by Tab.

### Keyboard navigation

- ArrowDown and ArrowUp move to the next and previous option.
- Stops at either end rather than wrapping.
- Home and End move to the first and last option.
- Disabled options are passed over.
- Options in groups are one sequence.
- A horizontal list moves with ArrowLeft and ArrowRight, mirrored right-to-left.
- In a list where focus follows the pointer, the option under it is focused.
- In such a list, releasing the pointer on an option chooses it, wherever the press began.
- PageUp and PageDown move by a page of options.
- In a horizontal list, PageUp and PageDown move by a page along it.
- Options that share a value do not trap the arrow keys.

### Typeahead

- Typing a character moves to the next option that starts with it.
- Typing quickly matches the whole prefix.
- Repeating a character cycles through the options that start with it.
- Matching ignores case and accents.
- A key that moves focus ends the query, so the next character starts afresh.
- A space continues a query that has started.
- An option's typeahead text may differ from its visible label.
- Leaving the list ends the query: what is typed on return starts afresh.

### Single selection

- A click selects the option.
- A tap selects the option. *(Chromium (touch), WebKit (touch))*
- Selection follows focus.
- With the command key held, arrows move focus and leave the selection.
- Toggle behaviour: arrows move focus only, and Space selects.
- The command key with A selects nothing: not the options, and not the text of the page.
- A click that no press came before, as assistive technology makes, selects the option.
- A secondary press selects the option it lands on. *(Chromium, Firefox, WebKit)*
- A long press on an option asks for its context menu, and selects it. *(Chromium (touch))*
- Command-click on the selected option clears the selection.
- When a selection is required, the selected option cannot be deselected.

### Multiple selection

- A click selects only that option.
- Command-click adds or removes one option and keeps the rest.
- Shift-click selects the range from the last clicked option.
- A second shift-click redraws the range from the same anchor.
- Shift-click after command-click adds a range to the selection.
- Arrows select as they move; with Shift they extend.
- With the command key held, arrows move focus and Space adds the option.
- Command-A selects every enabled option.
- Shift with an arrow extends a selection that was given, from the focused option.
- A press on one of several selected options keeps them all, until it ends as a click on that one. *(Chromium, Firefox, WebKit)*
- A secondary press within the selection keeps it, and outside it selects only what it lands on. *(Chromium, Firefox, WebKit)*
- An option that is selected but unavailable stays selected as others change.
- Toggle behaviour: every click adds or removes.
- A range never selects a disabled option.
- A tap adds or removes an option, since touch has no modifier keys. *(Chromium (touch), WebKit (touch))*
- Shift with Home or End extends the selection to that end, with the command key or without.
- Dragging across options selects the range it passes over. *(Chromium, Firefox, WebKit)*
- The range follows the pointer back as it returns, and on past where it began. *(Chromium, Firefox, WebKit)*
- With the command key held, a drag adds its range to what was selected. *(Chromium, Firefox, WebKit)*
- A drag from a selected option draws no range: the selection is that drag's to carry. *(Chromium, Firefox, WebKit)*
- A drag goes on outside the list, following the pointer along it. *(Chromium, Firefox, WebKit)*
- A drag held past the list's edge scrolls it, selecting as it goes, until it is released. *(Chromium, Firefox, WebKit)*
- In a horizontal list a drag selects along it, in either direction. *(Chromium, Firefox, WebKit)*
- A pen selects nothing as it presses; its drag adds the range it passes over, and its tap adds or removes. *(Chromium)*
- A gesture the platform takes back leaves the selection as it was before the press. *(Chromium (touch))*
- A long press adds the option and keeps the rest; lifting the finger does not undo it. *(Chromium (touch))*
- After a long press, the finger selects the range it passes over, and the list does not scroll under it. *(Chromium (touch))*
- A finger that moves before its press is long is scrolling, and selects nothing. *(Chromium (touch))*

### Actions

- Enter performs the focused option's action.
- A key held down performs the action once.
- A double click performs the option's action.
- By touch, a tap selects an option and a tap on the selected option performs its action. *(Chromium (touch), WebKit (touch))*
- Two quick taps select an option and perform its action, once. *(Chromium (touch), WebKit (touch))*
- By touch in a multiple selection, a tap performs the action while nothing is selected, and adds or removes once something is. *(Chromium (touch), WebKit (touch))*

### Ten thousand options

- An arrow key re-renders only the two options it moves between, each once.
- A click that adds an option re-renders that option and the one focus left.
- An arrow key reads the options once, and the text of none of them.
- Typing reads the text of options only as far as the one it finds.

## Reference implementation

React: `npx shadcn@latest add https://ui.publictheta.com/r/listbox.json`
