vaiperui

components / radio

Radio

RadioGroup renders a set of options from an array; Radio is the single native radio.

How to use

Use `RadioGroup` with an `options` array (like `Select`): it shares one `name`, works controlled (`value`) or not (`defaultValue`), and arrow keys move between options natively. Use `Radio` alone when you need full control of each row.

preview
Plan
Radio.tsx
import { RadioGroup } from "vaiperui";
<RadioGroup
label="Plan"
defaultValue="free"
onValueChange={(plan) => console.log(plan)}
options={[
{ value: "free", label: "Free", description: "For side projects" },
{ value: "pro", label: "Pro", description: "For small teams" },
{ value: "team", label: "Team", disabled: true },
]}
/>

Colors

preview
primary
success
warning
danger
colors.tsx
<RadioGroup variantColor="primary" options={options} defaultValue="free" />
<RadioGroup variantColor="success" options={options} defaultValue="free" />
<RadioGroup variantColor="warning" options={options} defaultValue="free" />
<RadioGroup variantColor="danger" options={options} defaultValue="free" />

Orientation

preview
vertical
horizontal
orientation.tsx
<RadioGroup orientation="vertical" options={options} />
<RadioGroup orientation="horizontal" options={options} />

Sizes

preview
sm
md
lg
sizes.tsx
<RadioGroup size="sm" options={options} />
<RadioGroup size="md" options={options} />
<RadioGroup size="lg" options={options} />

States

preview
You can change it later
helper
Pick one
error
disabled
states.tsx
<RadioGroup helperText="..." options={options} />
<RadioGroup errorMessage="..." options={options} />
<RadioGroup disabled options={options} />

Custom color

preview
Orange
Radio
custom-color.tsx
<RadioGroup customColor="#ff6600" options={options} />
<Radio name="single" label="A standalone radio" />

Props

PropValuesDefaultDescription
options{ value, label, description?, disabled? }[]noneThe options of the RadioGroup
value / defaultValuestringnoneControlled / uncontrolled selection
onValueChange(value: string) => voidnoneCalled with the selected value
namestringgeneratedShared name of the radios, so they submit with a <form>
labelstringnoneTitle of the group (a <legend>)
orientationvertical | horizontalverticalDirection of the options
helperText / errorMessagestringnoneText under the group; an error colors every radio
disabledbooleanfalseDisables every option
variantColorprimary | success | warning | dangerprimaryColor of the checked state and focus ring
customColorstring | { light, dark }noneAny CSS color (or a pair per theme). Overrides variantColor
sizesm | md | lgmdSize of the control and its text
animationnone | smooth | fast | bouncesmoothTransition when it toggles
RadioInputHTMLAttributes<HTMLInputElement>noneStandalone radio: label, helperText, errorMessage, the style props above, and every native input prop

Accessibility

  • `RadioGroup` renders a `<fieldset>` with a `<legend>` (from `label`) and an inner `role="radiogroup"` named by the same `label`.
  • Each option is a native `<input type="radio">` sharing one `name`, so the browser provides arrow-key navigation and a single tab stop.
  • Each option `label` names its radio and its `description` becomes the radio's `aria-describedby` text.
  • `errorMessage` sets `aria-invalid` on the fieldset and on every radio; `aria-describedby` on the fieldset points to the error or helper text.
  • `disabled` on the group disables the fieldset; an option can also be disabled on its own.

Keyboard

KeyAction
TabMoves focus into and out of the group (one stop, on the selected option).
Arrow keysMove to the next or previous option and select it (native radio behavior).
SpaceSelects the focused option when none is selected yet.

Keep in mind

  • Always pass `label` to `RadioGroup`; without it the group has no accessible name.
  • A standalone `Radio` has no group semantics: give related radios the same `name` and wrap them yourself.