# Radio

> A single option in a mutually exclusive set — pair radios sharing the same name into a group.

URL: https://apogee.avaui.dev/docs/radio
Last updated: 2026-10-15

A single option in a mutually exclusive set — pair radios sharing the same name into a group.

Last updated October 15, 2026

```astro
<Radio name="plan-hero" value="free" label="Free" checked />
<Radio name="plan-hero" value="pro" label="Pro" />
<Radio name="plan-hero" value="team" label="Team" />
```

## Add

```sh
npx @ava-ui/apogee add radio
```

No Apogee component dependencies.

## Usage

```astro
---
import Radio from '@/components/apogee/Radio/Radio.astro'
---
<Radio name="plan" value="free" label="Free" checked />
<Radio name="plan" value="pro" label="Pro" />
```

## API

`@composable` — exposed to Content Editors in AVA. Any other native `<input>` attribute (e.g. `checked`, `disabled`, `required`) passes through.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` | — | Group name — give every radio in the set the same value. |
| `value` | `string` | — | This radio’s value, submitted when checked. |
| `label` | `string` | — | Visible label, rendered in a `<label>` next to the input. Rich labels go in the default slot instead. |
| `id` | `string` | auto-generated | Ties the label to the input; set your own to target it elsewhere. |
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | Control and label size. |
| `hasError` | `boolean` | `false` | Marks the control invalid (`aria-invalid`, critical border). |
| `hint` | `string` | — | Supporting text under the label; the input lists it in `aria-describedby`. The label turns medium weight to read as a heading. |
| `class` | `string` | — | Extra classes on the wrapping `<div>`. |

## Hint

```astro
<Radio name="plan" value="pro" label="Pro" hint="Unlimited projects and priority support." />
```

## Slot label

```astro
<Radio name="plan" value="pro"><span><strong>Pro</strong> — €12 / month</span></Radio>
```

## Sizes

```astro
<Radio name="radio-sizes" value="small" label="Small" size="small" />
<Radio name="radio-sizes" value="medium" label="Medium" size="medium" />
<Radio name="radio-sizes" value="large" label="Large" size="large" />
```

## States

-   **Unchecked / Checked** — native `:checked`; a filled accent dot fades in.
-   **Hover** — border darkens on an unchecked, enabled radio.
-   **Focus** — a visible `focus-visible` ring (`--border-primary`).
-   **Disabled** — disabled fill, border and label colour; pointer becomes `not-allowed`. Pass the native `disabled` attribute.

```astro
<Radio name="states" value="a" label="Unchecked" />
<Radio name="states" value="b" label="Checked" checked />
<Radio name="states" value="c" label="Disabled" disabled />
<Radio name="states" value="d" label="Checked, disabled" checked disabled />
```

## Examples

A full group sharing one `name`:

```astro
<Radio name="delivery" value="standard" label="Standard (5–7 days)" checked />
<Radio name="delivery" value="express" label="Express (1–2 days)" />
```

## Accessibility

-   Real `<input type="radio">` — keyboard and AT support for free: `Tab` moves into the group, arrow keys move and select between radios that share a `name`.
-   Focus ring is always visible on keyboard focus.
-   Every radio needs a label — pass `label`, or an `aria-label` if you supply your own markup instead.
-   Give every radio in a group the exact same `name` so the browser treats them as one set.

## Tokens

| Token | Used for |
| --- | --- |
| `--border-neutral` | Unchecked border |
| `--foreground-neutral-faded` | Hover border (unchecked, enabled) |
| `--background-primary` | Checked border + fill |
| `--background-page` | Unchecked fill |
| `--outline-color-focus` | Focus ring |

## Do / Don’t

-   **Do** use Radio for a single choice from 2–5 mutually exclusive, always-visible options.
-   **Do** give every radio in a group the same `name`.
-   **Don’t** use a lone Radio outside a group — a single yes/no choice is a `Checkbox` or `Switch`.
-   **Don’t** let the option list grow past ~6 — switch to `Select`.

## Content

-   Label is a short noun phrase naming the option (not a question), sentence case, no ending punctuation.

## Related

[

RadioGroupA fieldset of Radio controls with one legend, hint and error.

](https://apogee.avaui.dev/docs/radio-group)[

CheckboxA native checkbox with a custom look. Toggle a single option, or one item in a multi-select list.

](https://apogee.avaui.dev/docs/checkbox)[

SwitchA toggle for an immediately-applied binary setting. A real checkbox under the hood, zero JS.

](https://apogee.avaui.dev/docs/switch)
