# Radio group

> One choice among a few, all in view: as segments in a row, or as a list with a mark beside each.

A radio group is one choice among a few, all in view: choosing one leaves the
others unchosen.

## When to use

Use a radio group for two to about seven choices that people should see side by
side before choosing — a delivery speed, an alignment, a view. Shown segmented,
as a row of a few short choices with the chosen one raised, it suits settings
that change what is in view at once; shown as a list, with a mark beside each
and room for a line that says more, it suits a form.

For a longer list, or one that must be searched by typing, use a
[listbox](https://ui.publictheta.com/components/listbox.md); to save room, a [select](https://ui.publictheta.com/components/select.md).
For on or off, a [checkbox](https://ui.publictheta.com/components/checkbox.md) or a toggle
[button](https://ui.publictheta.com/components/button.md).

## Why it is a component

A [listbox](https://ui.publictheta.com/components/listbox.md) with single selection already moves a choice
with the arrow keys, but it is a different control, with a different contract,
and assistive technology announces it as one:

- **Role.** A radio group is a set of radio buttons; a listbox is a list of
  options. People who use a screen reader expect each to behave as its role
  says.
- **Keyboard.** In a radio group, Tab enters on the chosen one and the next Tab
  leaves; the arrows of both axes move, and the choice follows focus — round
  from the last to the first. A listbox has Home and End, typeahead, selection
  that may not follow focus, multiple selection, and lives in popups.
- **Forms.** A radio group is the platform's own radio buttons, so a form
  submits the choice, checks that one is made when it must be, and resets it.

So it is built on the platform's radios, with the [keyboard
navigation](https://ui.publictheta.com/foundations/navigation.md) primitive moving the same way in every
engine.

## Best practices

**Label the group, and each choice.** The group's label says what is being
chosen; each choice's label, what it is. A line that says more is its
description, not part of its name.

**Choose a sensible default** where there is one, so the group is never empty
without reason; where a choice must be made, leave it empty and say it is
required.

**Keep the choices short and parallel.** Segments especially: a word or two
each.

**Disable rather than hide** a choice that is unavailable for now.

## Platform considerations

**Keyboard.** Tab enters the group on the chosen one — on the first, while none
is — and the next Tab leaves it. Down Arrow and the arrow toward the end of the
line move to the next choice and choose it; Up Arrow and the other go back;
both mirror in right-to-left text. Past the last, they come round to the first.
An unavailable choice is passed over. Space chooses the one with focus. WebKit
on macOS leaves radio buttons out of the Tab order unless the person has asked
for every control; that is the person's setting, and the group keeps it.

**Pointer.** A press on a choice or on its label chooses it; a segment is
pressed anywhere within it.

**Touch.** Each segment, and each line of a list, is at least 44 CSS pixels
tall.

**Forced colours.** The chosen segment, raised by shade and shadow elsewhere,
takes the system's highlight.

**Assistive technology.** It is a radio group, named by its label, of radio
buttons named by theirs, one of them checked; an unavailable choice is announced
as such, and a required group as required.

## 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 radio group named by its label, of radio buttons named by theirs, the chosen one checked.
- An unavailable choice is announced as such.
- A choice's description is its description, and not part of its name.
- Has no accessibility violations, segmented or as a list, in every state.

### Focus

- Tab enters the group on the chosen one, and the next Tab leaves it. *(Chromium, Chromium (touch), Firefox)*
- With nothing chosen, Tab enters on the first. *(Chromium, Chromium (touch), Firefox)*

### Keyboard

- Down and Right move to the next choice and choose it; Up and Left to the one before.
- An unavailable choice is passed over.
- Past the last, the arrows come round to the first, and back.
- In right-to-left text, Left goes on and Right goes back.
- With nothing chosen, Space chooses the one with focus.

### Pointer

- A click on a choice, or on its label, chooses it.
- A press anywhere on a segment chooses it.
- An unavailable choice cannot be chosen.
- Under a finger each segment, and each line of a list, is 44 pixels tall, and a tap chooses. *(Chromium (touch), WebKit (touch))*

### Appearance

- Segmented, the chosen segment is raised from the rest; where colours are forced it takes the system's highlight, and an unavailable one its grey.
- The chosen one is stated as `data-checked` and an unavailable one as `data-disabled`, which its styles read.

### Forms

- The choice is submitted under its name.
- A required group with nothing chosen keeps its form from being submitted.
- Two groups given no name do not share one.

## Reference implementation

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