---
title: Radio Group
description: Radio groups present mutually exclusive options. Only one choice can be selected at a time within the group.
category: Forms
---
import { meta as RadioGroupMeta, Default } from '@/content/stories/radio-group';
import Canvas from '@/components/component-docs/canvas';
import Demo from '@/components/component-docs/demo';
export const config = {
dependencies: {
components: [Canvas, Demo],
scripts: [
'../../components/component-docs/demo.script.tsx',
'../../components/component-docs/canvas.script.tsx',
'../../components/component-docs/controls.script.tsx',
],
},
};
# Radio Group
Radio groups present mutually exclusive options. Only one choice can be selected at a time within the group.
## Try it
## Usage
Set `value` for the selected option and provide radio inputs as children. Wrap in `RuiField` for form integration. Set `name` on the group (or the field) to list inner radios on native `FormData`.
```tsx
import { RuiRadio, RuiRadioGroup, RuiRadioGroupControl } from '@ecopages/radiant-ui/radio-group';
import { RuiField } from '@ecopages/radiant-ui/field';
import { RuiLabel } from '@ecopages/radiant-ui/label';
PlanFreePro
```
## Custom markup
`` coordinates any light-DOM tree that matches its query contract. The `Rui*` helpers stamp these targets; they are not required.
```tsx
import '@ecopages/radiant-ui/radio-group';
```
BEM classes are presentation-only. Do not set `name`, `checked`, or `disabled` on radios — the host owns those.
## Mutually exclusive choices
Use radio groups when options are mutually exclusive. For independent toggles that share one field value, use a checkbox group; for a single on/off toggle, use a checkbox.
## Theming
Radio group surfaces map to **semantic roles**, never Tailwind palette steps:
| Part | CSS roles |
| --- | --- |
| Option row (`.rui-radio`) | `on-background` text, `space-inline` gap |
| Control dot (`.rui-radio__control`) | `border`, `background`; `primary` when checked |
| Checked dot (`::after`) | `primary` fill |
| Focus ring | `focus-ring` |
| Disabled | `opacity-disabled` |
The custom control dot is decorative (`aria-hidden`), the visually hidden native radio input carries the accessible state. Override at the theme layer, not in component CSS.
## API
`RuiRadioGroup` is a custom element (``). Compose its options with `RuiRadioGroupControl` and `RuiRadio`, or use the convenience `options` prop to generate the same structure.
### Attributes
| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | `''` | Selected radio value. |
| `name` | `string` | `''` | Form field name shared by all radios in the group. |
| `label` | `string` | `''` | Accessible name when no visible legend is composed in the view. |
| `disabled` | `boolean` | `false` | Disables every radio in the group. |
### Light-DOM contract
| Target | Required | Host writes | Author owns |
| --- | --- | --- | --- |
| `[data-radio-group-root]` | yes | `aria-label`, `aria-disabled` | the group node |
| `input[type="radio"]` | yes (per option) | `name`, `checked`, `disabled` | `value`, `data-disabled` |
Do not set `name`, `checked`, or `disabled` on radios. Nested hosts: none.
### Events
| Event | Detail | Description |
| --- | --- | --- |
| `rui-change` | `{ value: string }` | Emitted after the selected value changes. |
### Props
| Prop | Type | Description |
| --- | --- | --- |
| `options` | `RuiRadioOption[]` | `{ value, label, disabled? }` entries rendered by the view. |
### View helpers
| Component | Target stamped | Notes |
| --- | --- | --- |
| `RuiRadioGroup` | `` | Accepts `options` or children. |
| `RuiRadioGroupControl` | `[data-radio-group-root]` | `role="radiogroup"` container. |
| `RuiRadio` | `input[type="radio"]` | Label-wrapped option with `value`. |
### CSS classes
Public BEM classes (documented via `@cssclass`):
| Class | Description |
| --- | --- |
| `.rui-radio-group` | Group surface (`role="radiogroup"`). |
| `.rui-radio` | Option label row (authored by the `RuiRadioGroup` view). |
| `.rui-radio__input` | Visually hidden native radio input. |
| `.rui-radio__control` | Custom control dot (mirrors check state). |
| `.rui-radio__label` | Option text. |
### Theme roles
| Part | CSS variables consumed |
| --- | --- |
| Option row | `--on-background`, `--space-inline` |
| Control dot | `--border`, `--background`, `--primary` |
| Focus | `--focus-ring` |
| Disabled | `--opacity-disabled` |
## Accessibility
- The group exposes `role="radiogroup"` with an accessible name from `label`.
- Arrow keys move selection between radio options.
- Visually indicate the selected option; do not rely on position alone.