Pre-alphaThe registry and the CLI are not published yet.Roadmap

Radio

Radio button and its RadioGroup.

Choose a plan
Yearly$48

$4 / month, billed yearly

Save 33%

Monthly$6
Cancel anytime
Family$96

Not available in your region

Installation

npx axiom add radio
pnpm dlx axiom add radio
yarn dlx axiom add radio
bun x axiom add radio

Colors come from radio.default.{default,checked,disabled}.{border,indicator} in the component tokens. RadioIndicator is exported to draw the circle inside a custom row.

Usage

import { Radio, RadioGroup } from "@/components/ui/radio";

<RadioGroup value={plan} onValueChange={setPlan}>
	<Radio value="monthly" label="Monthly" />
	<Radio value="yearly" label="Yearly" />
</RadioGroup>;

Props

RadioGroup

PropTypeDefaultDescription
valuestring—Value of the selected radio.
defaultValuestring—Initial selection when the group manages its own state.
onValueChange(value: string) => void—Called with the value of the radio the user pressed.
orientation'vertical' | 'horizontal''vertical'Layout direction of the radios.
gapSpacingToken3Space between radios.
disabledbooleanfalseDisables every radio in the group.
hapticHapticKind | false—Haptic played when the user picks another radio. Off unless you pass a kind.
accessibilityLabelstring—Name of the question, announced once for the group (accessibilityRole="radiogroup").
childrenReactNode—Radio elements, or any element wrapping them.
styleStyleProp<ViewStyle>—Extra styles for the group.

Radio

PropTypeDefaultDescription
valuestring—Required. Identifies the option within the group.
labelReactNode—Text next to the circle. The whole row is pressable.
descriptionReactNode—Secondary text under the label.
disabledbooleanfalseBlocks this option only.
children(state: { checked: boolean; pressed: boolean }) => ReactNode—Replaces the default row, to build a selectable card around the radio.
styleStyleProp<ViewStyle>—Extra styles for the row.

A Radio outside a RadioGroup doesn’t do anything useful: the group owns the selection.

Haptics

Radios play nothing by default. Pass a kind to RadioGroup, usually "selection", to play one when the user picks another option. Pressing the selected radio again plays nothing. Nothing plays until your app connects a haptics library: see Haptics.

Use cases

Delivery options

Label and description on each option, with the price as trailing content.

Delivery
Standard3–5 business days
Free
ExpressTomorrow before 12:00
$9.90
Pick up in storeRue de Rivoli, ready in 2h
Free
<RadioGroup
	value={delivery}
	onValueChange={setDelivery}
	accessibilityLabel="Delivery"
>
	<Radio value="standard" label="Standard" description="3–5 business days" />
	<Radio value="express" label="Express" description="Tomorrow before 12:00" />
	<Radio
		value="pickup"
		label="Pick up in store"
		description="Rue de Rivoli, ready in 2h"
	/>
</RadioGroup>

Selectable cards

The render function of Radio gives checked, to highlight the whole card and not only the circle.

How will you use Axiom?
PersonalSide projects and learning
TeamShared apps and reviews

Continue

<RadioGroup value={usage} onValueChange={setUsage} orientation="horizontal">
	<Radio value="personal">
		{({ checked }) => (
			<Card variant="outlined" style={checked && styles.selected}>
				…
			</Card>
		)}
	</Radio>
	<Radio value="team">{/* same */}</Radio>
</RadioGroup>

Short answer in a survey

Horizontal orientation for a few short labels that fit on one line.

QUESTION 3 OF 5Would you recommend us to a friend?
Yes
Maybe
No
<RadioGroup
	orientation="horizontal"
	gap={4}
	value={answer}
	onValueChange={setAnswer}
>
	<Radio value="yes" label="Yes" />
	<Radio value="maybe" label="Maybe" />
	<Radio value="no" label="No" />
</RadioGroup>