# Radio group

> A group of radio buttons for selecting one option from a set

Status: stable. Added in Components 2.0.0. Updated in Components 2.17.0, 24 Oct 2026.

A group of radio buttons for selecting one option from a set.

## Import

```tsx
import { RadioGroup } from '@oztix/roadie-components/radio-group'
```

## Examples

### Default

```tsx
<RadioGroup>
  <RadioGroup.Item value='email' label='Email' />
  <RadioGroup.Item value='phone' label='Phone' />
  <RadioGroup.Item value='post' label='Post' />
</RadioGroup>
```

### With Field

Wrap RadioGroup in [Field](https://ticketsolutionsptyltd.github.io/roadie/components/field.md) for consistent layout, labels,
and error handling.

```tsx
<Field required>
  <Field.Label showIndicator>Contact method</Field.Label>
  <RadioGroup>
    <RadioGroup.Item value='email' label='Email' />
    <RadioGroup.Item value='phone' label='Phone' />
    <RadioGroup.Item value='post' label='Post' />
  </RadioGroup>
</Field>
```

### With standalone label

RadioGroup also has its own `RadioGroup.Label` for standalone usage without a
Field wrapper.

```tsx
<RadioGroup required>
  <RadioGroup.Label showIndicator>Contact method</RadioGroup.Label>
  <RadioGroup.Item value='email' label='Email' />
  <RadioGroup.Item value='phone' label='Phone' />
  <RadioGroup.Item value='post' label='Post' />
</RadioGroup>
```

### Variants

#### Horizontal direction

```tsx
<RadioGroup direction='horizontal'>
  <RadioGroup.Item value='small' label='Small' />
  <RadioGroup.Item value='medium' label='Medium' />
  <RadioGroup.Item value='large' label='Large' />
</RadioGroup>
```

### Emphasis

Use the `emphasis` prop on the Root to control the visual weight of all items.

#### Normal

```tsx
<RadioGroup emphasis='normal'>
  <RadioGroup.Item value='standard' label='Standard delivery' />
  <RadioGroup.Item value='express' label='Express delivery' />
  <RadioGroup.Item value='overnight' label='Overnight delivery' />
</RadioGroup>
```

### Sizes

`md` is the default. Use `sm` in dense lists, such as a filter sidebar, and
`lg` where the choice is the main thing on the screen. Set it on the Root. With
`emphasis='normal'`, it sizes the circle only.

```tsx
{/* Small */}
<RadioGroup size='sm' defaultValue='a'>
  <RadioGroup.Item value='a' label='Option A' />
</RadioGroup>
{/* Medium */}
<RadioGroup size='md' defaultValue='a'>
  <RadioGroup.Item value='a' label='Option A' />
</RadioGroup>
{/* Large */}
<RadioGroup size='lg' defaultValue='a'>
  <RadioGroup.Item value='a' label='Option A' />
</RadioGroup>
```

### Trailing

`trailing` puts a count, `Badge`, or value at the end of an item. It isn't
part of the radio's name, so screen readers announce the label alone.

```tsx
<RadioGroup size='sm' defaultValue='upcoming'>
  <RadioGroup.Label>Event dates</RadioGroup.Label>
  <RadioGroup.Item value='upcoming' label='Upcoming' trailing='265' />
  <RadioGroup.Item value='next-7-days' label='Next 7 days' trailing='18' />
  <RadioGroup.Item value='next-30-days' label='Next 30 days' trailing='74' />
</RadioGroup>
```

### States

```tsx
{/* Default */}
<RadioGroup>
  <RadioGroup.Item value='a' label='Option A' />
  <RadioGroup.Item value='b' label='Option B' />
</RadioGroup>
{/* Invalid */}
<RadioGroup invalid>
  <RadioGroup.Item value='a' label='Option A' />
  <RadioGroup.Item value='b' label='Option B' />
</RadioGroup>
{/* Invalid and chosen */}
<RadioGroup invalid defaultValue='a'>
  <RadioGroup.Item value='a' label='Option A' />
  <RadioGroup.Item value='b' label='Option B' />
</RadioGroup>
{/* Disabled */}
<RadioGroup disabled defaultValue='a'>
  <RadioGroup.Item value='a' label='Option A' />
  <RadioGroup.Item value='b' label='Option B' />
</RadioGroup>
{/* One item disabled */}
<RadioGroup>
  <RadioGroup.Item value='a' label='Option A' />
  <RadioGroup.Item value='b' label='Option B' disabled />
</RadioGroup>
```

## Accessibility

- **Keyboard**: `Arrow Up`/`Arrow Down` moves between radio items. `Space` selects the focused item. Base UI manages roving tabindex.
- **ARIA**: Base UI Radio sets `role="radiogroup"` on the root and `role="radio"` with `aria-checked` on each item automatically. An invalid group, from `invalid` or its `Field`, sets `aria-invalid` on the `radiogroup`.
- **Grouping**: Wrap in a `Fieldset` with a `Legend` to provide a group label for screen readers.

## API reference

### RadioGroup

```tsx
import { RadioGroup } from '@oztix/roadie-components/radio-group'
```

- `disabled`: `boolean`. Defaults to `false`. Whether the component should ignore user interaction.
- `readOnly`: `boolean`. Defaults to `false`. Whether the user should be unable to select a different radio button in the group.
- `required`: `boolean`. Defaults to `false`. Whether the user must choose a value before submitting a form.
- `name`: `string`. Identifies the field when a form is submitted.
- `form`: `string`. Identifies the form that owns the radio inputs. Useful when the radio group is rendered outside the form.
- `value`: `any`. The controlled value of the radio item that should be currently selected. To render an uncontrolled radio group, use the `defaultValue` prop instead.
- `defaultValue`: `any`. The uncontrolled value of the radio button that should be initially selected. To render a controlled radio group, use the `value` prop instead.
- `onValueChange`: `((value: any, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element; }) => void)`. Callback fired when the value changes.
- `inputRef`: `Ref<HTMLInputElement>`. A ref to access the hidden input element.
- `className`: `string | ((state: RadioGroupState) => string)`. CSS class applied to the element, or a function that returns a class based on the component's state.
- `direction`: `"horizontal" | "vertical" | null`.
- `size`: `"sm" | "md" | "lg"`. Defaults to `'md'`. Sets every item's size.
- `emphasis`: `"subtler" | "normal"`.
- `invalid`: `boolean`.

### RadioGroup.ErrorText

No props beyond the standard HTML attributes.

### RadioGroup.HelperText

No props beyond the standard HTML attributes.

### RadioGroup.Item

- `value`: `any`. Required. The unique identifying value of the radio in a group.
- `disabled`: `boolean`. Whether the component should ignore user interaction.
- `required`: `boolean`. Whether the user must choose a value before submitting a form.
- `readOnly`: `boolean`. Whether the user should be unable to select the radio button.
- `inputRef`: `Ref<HTMLInputElement>`. A ref to access the hidden input element.
- `nativeButton`: `boolean`. Defaults to `false`. Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `true` if the rendered element is a native button.
- `className`: `string | ((state: RadioRootState) => string)`. CSS class applied to the element, or a function that returns a class based on the component's state.
- `label`: `ReactNode`. Names the radio. The whole row becomes the click target.
- `description`: `ReactNode`. A line of help under the label, read as the radio's description.
- `trailing`: `ReactNode`. End of the row: a count, `Badge`, or value. Left out of the accessible name.

### RadioGroup.Label

- `showIndicator`: `boolean`.

Docs updated 23 Oct 2026.
