RadioGroup

stable
Since 1.1
One-of-many choice as a list or as selectable cards, with icon, avatar, price, badge, and secondary-action slots.
Forms
primitive
Form Control
Needs State Matrix
import { RadioGroup } from '@ivim/native/components';

When to use

Use when
Exactly one option may be chosen and all options should stay visible.
Options need more than a label — a price, an icon, a badge — in which case use SelectableCardGroup.
Don't use when
More than one option may be chosen — use CheckboxGroup, or SelectableCardGroup with selectionMode="multiple".
There are many options or they are long — use Select so the list can scroll.
The choice is binary — use Toggle or a single Checkbox.

Playground

Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
Billing period
orientation
orientation
size
size
Required
isRequired
Invalid
isInvalid
Disabled
isDisabled
<RadioGroup />

Example

RadioGroup
Default
Billing period
Horizontal
Billing period
Required, with description
Billing period
*
You can change this at any time.
With an error
Billing period
One option disabled
Billing period
Whole group disabled
Billing period
Selectable cards
Simple cards
Plan
Icon cards with a badge and meta
Delivery
Avatar cards with a secondary action
Reviewer
Multi-choice cards (checkbox semantics)
Horizontal cards
Plan
Disabled card
Plan
Cards with an error
Plan
Platform adaptations
Untitled UI ships six separate selectable-card families. They differ only in what occupies the card’s leading slot and whether selection is single or multiple, so this implementation collapses them into one component with typed slots — keeping selection, disabled handling, and accessibility in a single place.

Anatomy

The parts that compose this component.
1
Group label
Names the choice; folded into each option’s accessible name.
2
Option
A radio row, or a card in SelectableCardGroup.
3
Leading slot
Card only — icon, avatar, or payment mark. What distinguishes the reference card families.
4
Meta and badge
Card only — trailing price or capacity, and an emphasis badge.
5
Secondary action
Card only — rendered outside the card’s pressable so it stays independently reachable.
6
Error message
Announces as an alert beneath the group.

Guidelines

Do
Always pass label so the group name reaches every option’s accessible name.
Do
Put a card’s secondary control in secondaryAction, so acting on it never selects the card.
Do
Preselect a sensible default when one exists, rather than starting with nothing chosen.
Don't
Use a radio group for two opposite states that could be one toggle.
Don't
Nest an interactive control inside a card’s title or description — it becomes unreachable behind the card’s own press target.

Props

Public props for this component. Required props are marked; defaults reflect the component implementation.
options
required
RadioOption[]
{ value, label, description?, isDisabled? }.
value / defaultValue
string | null
Controlled and uncontrolled selection.
onChange
(value: string) => void
Fires with the newly selected value.
label / description
ReactNode
Group name and supporting text. The label is folded into each option’s accessible name.
errorMessage
ReactNode
Announced as an alert; also puts options in the invalid treatment.
isRequired / isInvalid / isDisabled / isReadOnly
boolean
default: false
Group-level state; isDisabled overrides every option.
orientation
'vertical' | 'horizontal'
default: 'vertical'
Option stacking direction.
SelectableCardGroup: options
SelectableCardOption[]
{ value, title, description?, leading?, meta?, badge?, secondaryAction?, isDisabled? }.
SelectableCardGroup: selectionMode
'single' | 'multiple'
default: 'single'
Radio semantics, or checkbox semantics for multi-choice cards.
aria-label
string
Accessible name when there is no visible label, or when the label is not plain text.
size
'sm' | 'md'
default: 'md'
Control and label scale.

Accessibility

Roles and screen-reader behavior this component provides, plus keyboard interactions.
The group announces as radiogroup but is not itself an accessibility element, so each option stays individually reachable on iOS.
The group name is folded into each option’s accessible name, since React Native has no aria-labelledby.
Exactly one enabled option can be selected; a disabled option can never become selected.
SelectableCardGroup announces radio semantics in single mode and checkbox semantics in multiple mode.
A card’s secondaryAction sits outside the card’s pressable, so selecting and acting are distinct actions.
Error messages announce as alerts.
Tab
Moves focus into the group.
Space
Selects the focused option.
Arrow keys
Reserved for a future roving-focus pass; options are individually tabbable today.

Platform & RTL

Behavior that differs across the platforms this component runs on.
Web
Each option is focusable with a visible inset focus ring.
iOS
VoiceOver announces the radio trait, selected state, and the group name from each option’s label.
Android
TalkBack announces the radio trait and selected state.
RTL
Control, label, and card slots mirror with the writing direction.

State coverage

Interaction and visual states this component supports.
default
focus
error
disabled
selected

Token references

Semantic design tokens this component page exercises. Tap one to edit it live.