Skip to contentAsheeUIAsheeUI

Radio

One choice from a small set, drawn as a list of dots or a set of cards.

A radio group asks for exactly one option out of a set the reader can see. It is the honest control while the options still fit on the page: everything is visible at once, so comparing the choices costs no interaction. RadioGroup is the field, it carries the label, the description, the message and the status, and it owns the selection, and Radio is one option inside it, receiving the group's state, name and tokens through context.

Usage

import { Radio, RadioGroup } from "@asheeui/web";

<RadioGroup label="Delivery speed" defaultValue="standard">
  <Radio value="standard" label="Standard" />
  <Radio value="express" label="Express" />
</RadioGroup>

An uncontrolled group keeps the selection itself, which is enough while nothing else on the page needs it. Pass value and onChange when the selection has to live with the rest of the form, so the group reports the chosen value and the consumer decides what it means:

<RadioGroup label="Delivery speed" value={speed} onChange={setSpeed}>
  <Radio value="standard" label="Standard" />
  <Radio value="express" label="Express" />
</RadioGroup>

Variants

Two shapes, stated once for the whole group. default draws the circle and puts the label beside it; card makes each option a bordered panel, so the choices read as blocks rather than as lines. An application that wants cards everywhere states variant: "card" under components.radio and every group follows.

The variant changes the panel, not the circle: a card still draws the circle at the radius the radio resolves, while the panel rounds full down to xl, a card with pill corners would be two vocabularies at once.

Orientation

orientation defaults to vertical, a column of options. Set it to horizontal and the group lays the options in a row that wraps, which suits short labels that read as a single question; a column is the better shape when an option needs a description underneath it, because the descriptions then line up instead of fighting for the same line.

An option can be disabled on its own, and disabled on the group puts every option out of reach while the labels stay readable. Everything else is inherited: size, color, variant, status and the shared name come from the group unless the item states its own. A Radio used outside a group keeps its own checked or defaultChecked state.

Props

The group's table is the one to read for the field. label, description, message and status belong to the group, because a set of options has no single control to carry them, and value or defaultValue is the selection itself.

An item needs a value and a label. Everything else it renders, the circle's accent, its density, whether it is a dot or a card, whether it is available, arrives from the group unless the item states its own, and the item's own prop wins.

Registered defaults belong to the component rather than to the application: components.radio states variant: "default" and radius: "full", so a radio stays round and stays a radio whatever defaultVariant and defaultRadius say. color is not registered, so it does follow the application's defaultColor, and size is registered as md.

Accessibility

  • The group is a role="radiogroup" container. Its visible label names it through aria-labelledby, and the description and message are referenced with aria-describedby; the label is not attached to any one input, because none of them is the field.
  • Each option is a real <input type="radio"> inside its own <label>, so the visible text is the option's name and the checked state is the browser's. The arrow keys move between the options that share the group's generated name, and Space selects the option that has focus.
  • The circle is decoration drawn from the input's state, and the focus ring is drawn from focus-visible on that circle, so it appears for a keyboard and not for a pointer. An option's description sits inside the same label, so it is read as part of the option's name rather than linked separately.
  • disabled on an item takes it out of the tab order, and on the group takes every item with it while the labels stay readable. required marks the group's label; because a group has no single control to receive the attribute, state the rule in the description or the message as well.

The label, description and message behave as the field anatomy describes.