COMPONENTS / MOLECULES / al-radio-group← ALL COMPONENTS

Radio Group

<al-radio-group><ALRadioGroup> REACTbetaOPEN IN FIGMA ↗

Reference generated from the custom elements manifest — 10 properties, 3 slots, 1 events.

PLAYGROUND5 CONTROLS
PREVIEW / al-radio-group / ALTITUDE
Loading preview
Radio 1 Radio 2 Radio 3 Radio 4
direction
FLAGS
CODE — HTML / REACT

Guidance

AUTHORED · CITED TO SOURCE

A set of radios that are one question with exactly one answer. Like the checkbox group it renders a real <fieldset> and <legend> with one shared field note and error note — and on top of that it owns the selection: arrow keys move the checked item, the previous item is unchecked for you, and the selection wraps at both ends.

WHEN TO USE

  • The choices are mutually exclusive and the user must land on exactly one of them.
  • There are few enough options to show at once — roughly two to seven — and seeing them all is worth the vertical space.
  • Comparison matters. Radios put every option in front of the user at the same time, which a control that opens cannot do.

WHEN NOT TO USE

  • The user may choose more than one, or none. Radios cannot express either.USE CHECKBOX-GROUP →
  • The list is long. Past a handful of options the form becomes a wall and the choice is better made in a field that opens.USE SELECT →
  • The choice is between two states of one setting that takes effect immediately.USE TOGGLE →

DO

  • Give the group a label; it becomes the <legend> that names the question for everyone who reaches an option by keyboard or screen reader.
  • Preselect a sensible default when one exists. A radio group with nothing checked forces a choice the user may not have an opinion about.
  • Listen for onRadioGroupChange on the group. Its detail carries the newly checked radio's checked, name and value.
  • Use hideLegend rather than dropping label when the question is already asked by the surrounding UI.

DON’T

  • Don't add an arrangement prop or wrap the group in your own flex container. Items stack in a column by default; for a row, nest them in <al-layout direction="row" wrap>.
  • Don't manage the unchecking yourself. Arrow navigation moves the checked item, sets the new one, focuses its input and dispatches the change event in one step — a competing handler will double-fire it.
  • Don't offer a radio group with a single option. One radio cannot be unchecked once checked, which makes it a control the user can enter and never leave.
  • Don't use a radio group for an action. Selecting an option should change a value, not trigger navigation or a save.

ACCESSIBILITY IN PRACTICE

  • Arrow Left and Arrow Up move to the previous option, Arrow Right and Arrow Down to the next, and both wrap around the ends — the standard radio group keyboard model, implemented on the group rather than left to the browser across shadow boundaries.
  • Moving the selection also moves focus: the newly checked radio's inner input is focused directly, and disabled inputs are skipped by the selector that finds it.
  • Enter re-commits the currently targeted radio, so a keyboard user who arrived by Tab can confirm without hunting for Space.
  • The legend carries aria-describedby to the field note, so the helper text belongs to the question rather than to whichever option happens to be focused.

CONTENT GUIDELINES

  • Write the legend as the question and the options as its answers, so the two read as one sentence together.
  • Keep options parallel in structure and comparable in length. Uneven options read as if one of them is the recommended answer.
  • Order options by a real property — sequence, size, price, frequency — rather than alphabetically, so position carries meaning.
  • Explain a consequence in the field note rather than inside one option's label; a long label breaks the parallel scan of the set.

WHERE THIS CAME FROM

  • libs/al-web-components/components/radio-group/radio-group.tsArrow-key selection in both axes, the wrap at each end, the focus move to the newly checked input, and the change event dispatched with it.
  • libs/al-web-components/components/radio-group/radio-group.tsThe native fieldset and legend, with `aria-describedby` from the legend to the field note.
  • libs/al-web-components/components/radio-group/radio-group.tsThe slot documentation sending row arrangement to `al-layout` rather than to a prop here.
  • AGENTS.mdThe contract entry naming roving selection and single-selection enforcement as this component's reason to exist.

Each line above names a file and a literal string that must still appear in it.pnpm gate:guidance re-reads them from this built page, so guidance that has stopped being true fails a check rather than misleading you.

BOTH CHANGEDAltitude Design SystemFIGMA SET · Radio Group1:1 ON EVERY PROPERTYFROM TRACKED PROJECTION

Code and Figma each changed since the last confirmed sync. Neither side should be overwritten blindly.

DECIDED BY
CONTRACT DIFF
FIGMA SIDE
OBSERVED
LAST CONFIRMED SYNC
2026-08-28
PUBLIC SURFACE
10 ATTR · 3 SLOT · 1 EVENT · 0 PART

The component’s public surface — attributes and their value sets, slots, events, CSS parts and custom properties, from the manifest — compared against the Figma set’s property definitions.

CHECKEVIDENCEDETAILRESULT
Default stateAXEradio-group--DefaultPASS
Advanced statesAXE6 further storiesPASS
Screen readerMANUALNo screen-reader pass has been recorded for this component.NOT RECORDED
Keyboard navigationINTERACTION TESTSNo interaction tests and no manual keyboard pass.NOT RECORDED

MEASURED 2026-09-08 · 7 STORIES · AXE WCAG2A + WCAG2AA + WCAG21A + WCAG21AA + WCAG22AA

COLOR CONTRAST1 RULE FAILING

The CI gate disables color-contrast globally (libs/al-web-components/story-fixture/src/main.ts), so its result never reaches a test run. It is enabled for this measurement, and reported here whichever way it comes out.

RULEWHEREELEMENTS
color-contrastElements must meet minimum color contrast ratio thresholdsradio-group--Disabled1
import '@southleft/al-web-components/components/radio-group';
import { ALRadioGroup } from '@southleft/al-react';
PROPTYPEDEFAULT
isErrorbooleanError state - Changes the component's treatment to represent an error state
isDisabledbooleanDisabled attribute - Changes the component's treatment to represent a disabled state
isRequiredbooleanRequired attribute - Sets the radio to be required for validation
hideLegendbooleanHide legend? - If true, hides the legend from displaying
direction'row' | 'column'Direction - **column** (default) stacks the radios - **row** lays them out inline, wrapping when they run out of room This does NOT re-introduce a hand-rolled arrangement prop. The group already renders an `<al-layout>` around its slotted items; this parameterises THAT layout rather than styling the items here, so `<al-layout>` remains the single arrangement primitive. The row form is a documented variant of the group in the design library (Radio Group example, "Horizontal" column), which is why it earns a prop instead of being left to each consumer to compose.
labelstringLabel - Displays inside the legend
errorNotestringError message - An error field note that displays below the radio input
fieldNotestringField note - The helper text that displays below the radio input
fieldIdstringId attribute - The ID used for A11y and to associate the label with the input
ariaDescribedBystringaria-describedby attribute - Applied to the field note or error note for A11y
SLOTDESCRIPTION
(default)The radio content, a set of radio items. Items stack in a column by default; for a row, nest them in `<al-layout direction="row" wrap>`.
field-noteIf content is slotted, it will display in place of the fieldNote property
errorIf content is slotted, it will display in place of the errorNote property
EVENTDESCRIPTIONTYPE
onRadioGroupChangeFired when the group's selection changes. Detail: `{ checked, name, value }` — taken from the newly checked radio.CustomEvent
METHODDESCRIPTION
handleOnRadioChange()When a new item is checked: 1. Set the previously checked item's isChecked state to false 2. Store the newly checked item on the radio's state
setCheckedAdjacentItem()Set the checked radio to the previous or next radio based on the 'isPrevious' flag
handleOnKeydown()Handle on keydown events 1. Check if a radio is already checked, else use the target 2. If the enter key is pressed, then check the radio and dispatch the custom event 3. If arrow left or arrow up is pressed, set previous radio as checked 4. If arrow right or arrow down is pressed, set next radio as checked

SOURCE — components/radio-group/radio-group.ts · Molecules/Form/Radio Group