<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# RadioGroup

A group of radios under one legend, on the Field contract, for picking exactly one choice: pass `legend`, and `options` (or `Radio` children). The group is one tab stop; the arrow keys move between radios and pick as they go. With `name`, the chosen value submits as `name=value` with its form. `error` and `required` apply to the whole group.

```tsx
import { RadioGroup } from "@/components/ouro/radio-group/radio-group";
```

## Example

```tsx
<RadioGroup
  legend="Size"
  name="size"
  defaultValue="medium"
  options={[
    { value: "small", label: "Small", description: "Serves 2." },
    { value: "medium", label: "Medium", description: "Serves 4." },
  ]}
/>
```

## Use instead when

- Use `CheckboxGroup` instead when several choices may be picked, `Select` for a long list, and `Switch` for on or off.

## Props

The props the modes share. Type: `RadioGroupProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, width, grid placement (`mt-4`, `col-span-2`). Appearance classes warn in development; style radios in your theme. |
| `defaultValue` | `string` |  | The value chosen at first, for an uncontrolled group. Unset, nothing is chosen. |
| `description` | `ReactNode` |  | Supporting text under the legend, read after it through `aria-describedby`. |
| `disabled` | `boolean` |  | Disables every radio and fades the group. |
| `error` | `ReadonlyErrorMessages` |  | What is wrong, from your server action or client check, shown under the choices; every radio gets `aria-invalid`. A message is text or a React node (one with a link); an empty string or array means valid. |
| `hideLegend` | `boolean` |  | Hides the legend visually; screen readers still read it as the group's name. |
| `legend` (required) | `string` |  | What is being chosen, shown above the choices and read as the group's name. Required: a group of controls needs a name. To hide it visually, keep it and add `hideLegend`. |
| `name` | `string` |  | The form field name the chosen value submits under. |
| `onValueChange` | `((value: string) => void)` |  | Called with the chosen value when another radio is picked. |
| `orientation` | `"vertical" \| "horizontal"` | `"vertical"` | `vertical` stacks the choices; `horizontal` puts short ones in a row that wraps. |
| `ref` | `Ref<HTMLDivElement>` |  | The group element, a `<div role="radiogroup">`. |
| `required` | `boolean` |  | A choice must be picked to submit the form: the group gets `aria-required`, and the legend a marker. |
| `value` | `string` |  | The chosen value, for a controlled group; pair it with `onValueChange`. |

## Modes

`RadioGroupProps` is a union: pass the props of exactly one mode. Mixing them is a type error.

### With `children`

| Prop | Type | Description |
| --- | --- | --- |
| `children` (required) | `ReactNode` | The choices as `Radio` elements, for a layout `options` cannot express. |

Not in this mode (typed `never`):

- `options`: Not with children: pass the choices one way.

### With `options`

| Prop | Type | Description |
| --- | --- | --- |
| `options` (required) | `RadioGroupOption[]` | The choices, one radio each, in order. |

Not in this mode (typed `never`):

- `children`: Not with `options`: pass the choices one way.

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `errorMessage`: Not a prop. Ouro UI uses `error`: `<RadioGroup error="Required.">`.
- `helperText`: Not a prop. Ouro UI uses `description`: `<RadioGroup description="...">`.
- `invalid`: Not a prop. `error` marks the group invalid: `<RadioGroup error="What is wrong">`.
- `isDisabled`: Not a prop. Ouro UI uses `disabled`: `<RadioGroup disabled>`.
- `isInvalid`: Not a prop. `error` marks the group invalid: `<RadioGroup error="What is wrong">`.
- `isRequired`: Not a prop. Ouro UI uses `required`: `<RadioGroup required>`.
- `items`: Not a prop. Ouro UI uses `options`: `options={[{ value: "small", label: "Small" }]}`.
- `label`: Not a prop. A group is named by its `legend`: `<RadioGroup legend="Size">`.
- `onChange`: Not a prop. Ouro UI uses `onValueChange`, which gets the chosen value: `onValueChange={setSize}`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`).

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

## Types

### `ErrorMessage`

One error message: text, or a React element for a message that carries a link or other markup.

```ts
type ErrorMessage = string | ReactElement;
```

### `RadioGroupOption`

One choice in a `RadioGroup`'s `options`.

```ts
interface RadioGroupOption {
  /** What the group submits when this choice is picked, and the group's `value` then. */
  value: string;
  /** The choice's name, shown to the right of its radio. */
  label: string;
  /** Supporting text under the label, read after it. */
  description?: ReactNode | undefined;
  /** Disables this one radio; the arrow keys skip it. */
  disabled?: boolean | undefined;
}
```

### `ReadonlyErrorMessages`

A read-only message view accepted by fields and Form; mutable input arrays remain valid.

```ts
type ReadonlyErrorMessages = ErrorMessage | readonly ErrorMessage[];
```
