# RadioGroup

> Package `@umriss-ui/core`, version 0.40.0. Demo page: <https://romanhaendler.github.io/umriss-ui/core/radiogroup/>. Every page in one line: [llms.txt](https://romanhaendler.github.io/umriss-ui/core/llms.txt); every page in full: [llms-full.txt](https://romanhaendler.github.io/umriss-ui/core/llms-full.txt).

One choice out of a few that all stay in view (radio buttons, option group). Each option may carry a sentence that explains it.

```ts
import { RadioGroup } from "@umriss-ui/core";
```

Demo page: https://romanhaendler.github.io/umriss-ui/core/radiogroup/

The group is one tab stop; the arrow keys move and choose at once, skipping disabled options, which stay visible.

## Examples

### Radio group

Pass the choices as `options`; the group takes one tab stop, and the arrow keys move and choose at once.

```tsx
import { useState } from "react";
import { FormField, RadioGroup } from "@umriss-ui/core";

export default function RadioGroupExample() {
  const [attempt, setAttempt] = useState("neighbour");

  return (
    <FormField label="If nobody is home">
      <RadioGroup
        value={attempt}
        onChange={setAttempt}
        options={[
          { value: "door", label: "Leave at the door" },
          { value: "neighbour", label: "Hand to a neighbour" },
          { value: "depot", label: "Take back to the depot" },
        ]}
      />
    </FormField>
  );
}
```

### Descriptions

Give an option a `description` when the choice needs a sentence; a `disabled` option stays visible and is skipped.

```tsx
import { useState } from "react";
import { FormField, RadioGroup } from "@umriss-ui/core";

export default function Descriptions() {
  const [service, setService] = useState("standard");

  return (
    <FormField label="Delivery service" style={{ maxWidth: 480 }}>
      <RadioGroup
        value={service}
        onChange={setService}
        options={[
          { value: "standard", label: "Standard", description: "Within two working days, at no extra charge." },
          { value: "next-day", label: "Next day", description: "Booked before 14:00, delivered the next working day." },
          { value: "same-day", label: "Same day", description: "Booked before 10:00, delivered by 18:00 within the city." },
          { value: "pick-up", label: "Pick-up point", description: "No pick-up point within 2 km of this address.", disabled: true },
        ]}
      />
    </FormField>
  );
}
```

### Side by side

Set `orientation="horizontal"` for a few short labels without descriptions.

```tsx
import { useState } from "react";
import { FormField, RadioGroup } from "@umriss-ui/core";

export default function SideBySide() {
  const [part, setPart] = useState("full");

  return (
    <FormField label="Leave on Friday, 20 March">
      <RadioGroup
        orientation="horizontal"
        value={part}
        onChange={setPart}
        options={[
          { value: "morning", label: "Morning" },
          { value: "afternoon", label: "Afternoon" },
          { value: "full", label: "Full day" },
        ]}
      />
    </FormField>
  );
}
```

### States

With no `defaultValue` nothing is chosen yet; errors come from the `FormField`, and `disabled` on the group locks every option.

```tsx
import { FormField, Grid, RadioGroup } from "@umriss-ui/core";

const KINDS = [
  { value: "annual", label: "Annual leave" },
  { value: "sick", label: "Sick leave" },
  { value: "training", label: "Training, counted as working time but blocked for project work" },
];

export default function States() {
  return (
    <Grid minItemWidth="240px" gap={5}>
      <FormField label="Kind of absence" error="Choose the kind of absence.">
        <RadioGroup options={KINDS} />
      </FormField>
      <FormField label="Kind of absence" hint="Approved, no longer editable.">
        <RadioGroup options={KINDS} defaultValue="annual" disabled />
      </FormField>
      <FormField label="Kind of absence" hint="Small size.">
        <RadioGroup size="sm" options={KINDS} defaultValue="training" />
      </FormField>
    </Grid>
  );
}
```

## When to use something else

- Two to four short options without explanations, standing among fields → SegmentedControl
- More than about five options, or options that need no explanation → Select
- A single yes or no → Checkbox
- Several options at once → MultiSelect

## Keyboard

| Key | Action |
|---|---|
| `Tab` | Moves into the group, onto the chosen option, and out again. |
| `Arrow Down / Arrow Right` | Chooses the next option, wrapping at the end. |
| `Arrow Up / Arrow Left` | Chooses the previous option. |

## API

### `RadioGroupProps<T extends string>`

| Prop | Type | Default | Description |
|---|---|---|---|
| `options` *required* | `readonly `[`RadioOption`](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#type-RadioOption)`<T>[]` | — | The possibilities, in the order in which they are meant to stand.<br>Shown in: [Configurator](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#configurator-radiogroup), [Radio group](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#radio-group), [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions) and 5 more |
| `defaultValue` | `T \| null` | — | Initial value of an uncontrolled group. Not together with `value`.<br>Shown in: [Configurator](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#configurator-radiogroup), [States](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#states), [A row of fields (Sizes)](https://romanhaendler.github.io/umriss-ui/core/sizes/#a-row-of-fields) |
| `value` | `T \| null` | — | The chosen possibility; `null` means: none yet. Together with `onChange` the group is controlled.<br>Shown in: [Radio group](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#radio-group), [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Side by side](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#side-by-side) and 2 more |
| `orientation` | `"vertical" \| "horizontal"` | `"vertical"` | Arrangement: one below the other, or side by side.<br>Shown in: [Configurator](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#configurator-radiogroup), [Side by side](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#side-by-side), [A row of fields (Sizes)](https://romanhaendler.github.io/umriss-ui/core/sizes/#a-row-of-fields) |
| `size` | `"sm" \| "md"` | the size of a `ControlSizeProvider` around it, else `"md"` | `sm` for a toolbar and dense forms, `md` otherwise.<br>Shown in: [Configurator](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#configurator-radiogroup), [States](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#states) |
| `disabled` | `boolean` | `false` | Disables the whole group. `RadioOption` disables single possibilities.<br>Shown in: [Configurator](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#configurator-radiogroup), [States](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#states) |
| `name` | `string` | a generated one | Name of the radio group within the form. |
| `ref` | `Ref<HTMLDivElement>` | — | Receives the component's root element. From `RefProp`.<br>Shown in: [A row that holds still (Sizes)](https://romanhaendler.github.io/umriss-ui/core/sizes/#a-row-that-holds-still), [An anchored surface (Popover)](https://romanhaendler.github.io/umriss-ui/core/popover/#anchored-surface), [Take the width of the trigger (Popover)](https://romanhaendler.github.io/umriss-ui/core/popover/#width-from-anchor) and 2 more |

#### Events

| Prop | Type | Default | Description |
|---|---|---|---|
| `onChange` | `(value: T) => void` | — | Runs on every choice – on the one made with the arrow keys as well.<br>Shown in: [Radio group](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#radio-group), [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Side by side](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#side-by-side) and 2 more |

Also takes every attribute of `<div>` – without `defaultValue`, `onChange`.

### `RadioOption<T extends string>`

| Prop | Type | Default | Description |
|---|---|---|---|
| `value` *required* | `T` | — | What comes back when this possibility is chosen.<br>Shown in: [Radio group](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#radio-group), [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Side by side](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#side-by-side) and 3 more |
| `label` *required* | `ReactNode` | — | What stands beside it.<br>Shown in: [Radio group](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#radio-group), [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Side by side](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#side-by-side) and 3 more |
| `description` | `ReactNode` | — | Line of explanation under the label; it is read out as well.<br>Shown in: [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Approve spending against a budget (Scenarios)](https://romanhaendler.github.io/umriss-ui/core/#approve-spending), [Set up a team (Scenarios)](https://romanhaendler.github.io/umriss-ui/core/#set-up-a-team) |
| `disabled` | `boolean` | — | Takes the possibility out of the choice but leaves it visible: a choice that does not exist is a different statement from one that may not be made.<br>Shown in: [Descriptions](https://romanhaendler.github.io/umriss-ui/core/radiogroup/#descriptions), [Approve spending against a budget (Scenarios)](https://romanhaendler.github.io/umriss-ui/core/#approve-spending) |
