Radio Group
Picks exactly one option from a short list, as classic radios or as selectable cards with a title and description.
Preview
Installation
pnpm add @syntara/react @syntara/tokensimport { RadioGroup, Radio } from '@syntara/react';Usage
import { Radio, RadioGroup } from '@syntara/react';
export function Payout() {
return (
<RadioGroup variant="card" label="How should we pay you?" defaultValue="bank">
<Radio value="bank" description="1–2 working days. No fee.">Bank transfer</Radio>
<Radio value="instant" description="In minutes. 1% fee.">Instant payout</Radio>
</RadioGroup>
);
}Examples
Cards
variant="card": the whole card is the target; the description is linked, not part of the name.
Cards in a row
Wraps to a column on narrow screens.
Horizontal
Invalid and disabled
Accessibility
| Keys | Action |
|---|---|
| Tab | Moves focus to the selected radio (or the first), then out of the group. |
| Arrow keys | Move to and select the next/previous option, skipping disabled ones. |
| Space | Selects the focused radio if nothing is selected. |
- Uses native radio inputs inside a radiogroup.
- In the card variant the label stretches over the card, so the whole card is clickable, and the focus ring is drawn around the card.
- Selected cards get a 2px primary edge and a tinted fill, not colour alone.
Guidelines
Do
- Use for 2–6 mutually exclusive options that should all be visible.
- Use cards when each option needs a sentence of explanation (fees, timing).
- Preselect a sensible default when there is one.
Don’t
- Don't use radios for more than about 7 options; use a Select.
- Don't put interactive elements inside a card; the whole card is the target.
API reference
RadioGroup
labelReactNodeGroup label. Without one, pass aria-label.
descriptionReactNodeHelp text under the group label.
errorMessagestring | ((validation: ValidationResult) => string)Shown with an icon when invalid.
variantdefaultdefaultcard
card renders each Radio as a selectable card (title = children, plus description).
orientationhorizontalverticaldefault
Layout. Horizontal cards share the row and wrap when narrow.
value / defaultValuestring | nullControlled / uncontrolled selected value.
onChange(value: string) => voidCalled when the selection changes.
isRequired / isInvalid / isDisabledbooleanValidation and disabled state.
Default
false
Radio
valueRequiredstringUnique value of this option.
childrenReactNodeThe label (the card title in the card variant).
descriptionReactNodeSecondary text, linked with aria-describedby.
isDisabledbooleanDisables this option; arrow keys skip it.
Default
false
Tokens
The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.
- Colour15
action.primary.bgaction.primary.fgaction.primary.hoverborder.defaultborder.strongborder.subtlefeedback.danger.onSolidfeedback.danger.solidfocus.ringsurface.defaultsurface.selectedsurface.sunkentext.defaulttext.disabledtext.subtle- Type4
font.size.mdfont.size.smfont.weight.mediumline-height.normal- Space and size8
control-heightspace.1space.16space.2space.3space.4space.5space.6- Shape1
radius.field- Depth2
shadow.highlightshadow.raised- Motion5
motion.duration.fastmotion.duration.springmotion.easingmotion.springmotion.duration.normal