Radio Group
Overview
A set of checkable radio buttons where no more than one button can be checked at a time. It ships as a data-driven group and a card variant with icon/description content, both built on roving-focus keyboard navigation. Use it for single-choice from a small, mutually exclusive set; when multiple values are allowed, use SCheckboxGroup; when the option set is too large to scan at once, prefer SSelect.
Usage
Features
- ☑️ Single-choice model —
modelValue/defaultValuewith both controlled and uncontrolled modes - ⌨️ Roving-focus keyboard navigation — Arrow keys move and check, Enter/Space select, optional
loop - 🏷 Accessible labels —
RadioGroupLabelwiresforto each control’sid - 📋 Native form proxy — a visually hidden input carries the current value with
name/required - 🃏 Card variant (
SRadioGroupCard) with icon, label, and description content - 🎨 6 sizes, 8 colors, and dot/outline variants via
radioGroupVariants - 📊 Data-driven
RadioGroupCompact/RadioGroupCardCompactaggregation in Aria - ♿
role="radiogroup"+role="radio"witharia-checked/data-statedual reflection, axe-clean
Component family
SRadioGroup- data-driven radio group with dot/outline variantsSRadioGroupCard- card radio group with icon, label, and description
Demos
Basic
Card
This is an apple
This is an orange
This is a banana
This is a grape
API
Aria Layer
9RadioGroup<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
variant | RadioGroupVariant | — | Visual variant of the component. |
color | ThemeColor | — | Theme color of the component. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<RadioGroupUi> | — | Per-slot class overrides for the component. |
items | T[] | — | Items rendered by the component. |
itemProps | RadioGroupItemProps | — | Properties forwarded to the item element. |
controlProps | RadioGroupControlProps | — | Properties forwarded to the control element. |
indicatorProps | RadioGroupIndicatorProps | — | Properties forwarded to the indicator element. |
labelProps | LabelProps | — | Properties forwarded to the label element. |
modelValue | T['value'] | null | — | The controlled value of the radio item to check. Can be bound as `v-model`. |
defaultValue | T['value'] | — | The value of the radio item that should be checked when initially rendered. Use when you do not need to control the
state of the radio items. |
disabled | boolean | — | When `true`, prevents the user from interacting with radio items. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the radio group when applicable. |
loop | boolean | — | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | T | null | Event handler called when the radio group value changes |
RadioGroupCard<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
variant | RadioGroupVariant | — | Visual variant of the component. |
color | ThemeColor | — | Theme color of the component. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<RadioGroupCardUi> | — | Per-slot class overrides for the component. |
contentProps | BaseProps | — | Properties forwarded to the content element. |
textContentProps | BaseProps | — | Properties forwarded to the text content element. |
descriptionProps | BaseProps | — | Properties forwarded to the description element. |
items | T[] | — | Items rendered by the component. |
itemProps | RadioGroupItemProps | — | Properties forwarded to the item element. |
controlProps | RadioGroupControlProps | — | Properties forwarded to the control element. |
indicatorProps | RadioGroupIndicatorProps | — | Properties forwarded to the indicator element. |
labelProps | LabelProps | — | Properties forwarded to the label element. |
modelValue | T['value'] | null | — | The controlled value of the radio item to check. Can be bound as `v-model`. |
defaultValue | T['value'] | — | The value of the radio item that should be checked when initially rendered. Use when you do not need to control the
state of the radio items. |
disabled | boolean | — | When `true`, prevents the user from interacting with radio items. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the radio group when applicable. |
loop | boolean | — | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | T | null | Event handler called when the radio group value changes |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
description | { item: T; } | Slot for rendering custom description content within the radio card. |
RadioGroupCardCompact<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
contentProps | BaseProps | — | Properties forwarded to the content element. |
textContentProps | BaseProps | — | Properties forwarded to the text content element. |
descriptionProps | BaseProps | — | Properties forwarded to the description element. |
items | T[] | — | Items rendered by the component. |
itemProps | RadioGroupItemProps | — | Properties forwarded to the item element. |
controlProps | RadioGroupControlProps | — | Properties forwarded to the control element. |
indicatorProps | RadioGroupIndicatorProps | — | Properties forwarded to the indicator element. |
labelProps | LabelProps | — | Properties forwarded to the label element. |
modelValue | T['value'] | null | — | The controlled value of the radio item to check. Can be bound as `v-model`. |
defaultValue | T['value'] | — | The value of the radio item that should be checked when initially rendered. Use when you do not need to control the
state of the radio items. |
disabled | boolean | — | When `true`, prevents the user from interacting with radio items. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the radio group when applicable. |
loop | boolean | — | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | T | null | Event handler called when the radio group value changes |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
description | { item: T; } | Slot for rendering custom description content within the radio card. |
RadioGroupCompact<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | T[] | — | Items rendered by the component. |
itemProps | RadioGroupItemProps | — | Properties forwarded to the item element. |
controlProps | RadioGroupControlProps | — | Properties forwarded to the control element. |
indicatorProps | RadioGroupIndicatorProps | — | Properties forwarded to the indicator element. |
labelProps | LabelProps | — | Properties forwarded to the label element. |
modelValue | T['value'] | null | — | The controlled value of the radio item to check. Can be bound as `v-model`. |
defaultValue | T['value'] | — | The value of the radio item that should be checked when initially rendered. Use when you do not need to control the
state of the radio items. |
disabled | boolean | — | When `true`, prevents the user from interacting with radio items. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the radio group when applicable. |
loop | boolean | — | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | T | null | Event handler called when the radio group value changes |
RadioGroupControl
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Id of the element |
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
RadioGroupIndicator
Props
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | — | Used to force mounting when more control is needed.
Useful when controlling animation with Vue animation libraries. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
RadioGroupItem
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | DefinedWithBooleanValue | — | The value given as data when submitted with a `name`. |
disabled | boolean | — | When `true`, prevents the user from interacting with the radio item. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
select | RadioSelectEvent | Event handler called when the radio item is selected |
RadioGroupLabel
RadioGroupRoot<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | T | null | — | The controlled value of the radio item to check. Can be bound as `v-model`. |
defaultValue | T | — | The value of the radio item that should be checked when initially rendered. Use when you do not need to control the
state of the radio items. |
disabled | boolean | — | When `true`, prevents the user from interacting with radio items. |
orientation | DataOrientation | — | The orientation of the component. |
dir | Direction | — | The reading direction of the radio group when applicable. |
loop | boolean | — | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | T | null | Event handler called when the radio group value changes |
Notes
Architecture and benchmark differences
VeanUI builds the radio group from Aria RadioGroupRoot (useControllableState + useRovingFocusGroup) → RadioGroupItem (checked derivation + VisuallyHiddenInput form proxy) → RadioGroupControl (Button base + role="radio" + aria-checked/data-state, focus-derived selection) → RadioGroupIndicator (usePresence conditional mount) → RadioGroupLabel (for ↔ control id). RadioGroupCompact / RadioGroupCardCompact own item iteration and default composition while the UI wrappers only inject variant classes. The scv() recipes radioGroupVariants / radioGroupCardVariants declare 6 sizes, 8 colors, and dot/outline variants.
| Capability | VeanUI | Ant Design Radio | Element Plus Radio | Mantine Radio | Naive UI Radio | shadcn RadioGroup |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — | — | ✅ |
| Single-choice exclusive | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Roving-focus keyboard nav | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Controlled/uncontrolled | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Card variant (icon/description) | ✅ | — | — | — | — | — |
button variant | ➕ | ✅ | ✅ | — | — | — |
Radio.Button composite | ➕ | ✅ | — | — | — | — |
Form proxy / name submit | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Axe-clean (group + card) | ✅ | — | — | — | — | — |
Cautions
- Arrow-key selection commits through a focus-derived click on the control, so it flows through the same
radio.select/update:modelValuepath as mouse clicks. - The form proxy renders when a
nameis present on aform-classed root; pair it with a native<form>or theSFormintegration. selectis a cancellable custom event — callevent.preventDefault()to veto the value change.- Enter is wired explicitly to the select handler (matching the checkbox family); Space relies on the native button click behavior.
FAQ
How does keyboard navigation work?
The group uses roving focus: one radio is tabbable, Arrow keys move focus (and check the focused radio), Enter/Space select. Set loop to cycle from last to first and vice versa.
Controlled or uncontrolled?
Pass modelValue with v-model for a controlled value; pass defaultValue to let the group own its state internally. Both are supported via useControllableState.
How do I submit the selected value with a form?
Give the group a name; inside a form-classed root a visually hidden input carries the current value so native form submission picks it up.
What is the difference between SRadioGroup and SCheckboxGroup?
SRadioGroup enforces single choice — selecting one radio unchecks the others; SCheckboxGroup allows multiple checked values. Use radio for mutually exclusive options.