# Radio

A cross-platform React radio button component for selecting one option from a group. Works standalone or with RadioGroup for coordinated selection.

<!-- BEGIN:xui-mcp-instructions:radio -->
A single-select control used when only one option can be chosen from a list. Radio buttons are always presented as a group — a standalone radio is not meaningful on its own.

### When to use

- When the user must choose exactly one option from a set
- When all options need to be visible at the same time for comparison
- When there are 2–6 options of equal weight
- Inside the Autocomplete and Select via Context-menu

### When not to use

When the user can select more than one option — use Checkbox or ToggleButtonGroup
- When there are many options and space is limited — use a Select
- When options are compact and visually equal — consider ToggleButtonGroup
- For a single binary toggle — use a Switch

### Content guidelines

Label each option clearly and concisely — one short phrase, no trailing punctuation.

Use parallel structure across all options in the same group (all nouns, or all short phrases).

Use Description to add clarifying context when the label alone is not sufficient.

List options in a logical order — most common first, alphabetical, or by value.

Avoid negative options (e.g. *"Do not notify me"*) — rephrase positively.

### Behaviour guidelines

Only one radio in a group can be checked at a time — selecting one automatically unchecks the others.

A radio cannot be unchecked by clicking it again. To clear a selection, a *"None"* or *"Reset"* option must be provided explicitly.

Disable items remain visible but cannot be interacted with.

The Error state is typically applied to all items in the group (or to the group container) when validation fails — not to individual items.

### Accessibility

Wrap the group in a <fieldset> with a <legend> that names the group, or use role=*"radiogroup"* with aria-labelledby.

Each radio input should use role=*"radio"* with aria-checked=*"true"* or *"false"*.

Apply aria-disabled=*"true"* to disabled items.

Error messages should be linked to the group via aria-describedby.

Never rely on color alone to communicate the error state — always show the error message text.
<!-- END:xui-mcp-instructions:radio -->

## Installation

```bash
npm install @xsolla/xui-radio
```

## Demo

### Basic Radio

```tsx
import * as React from "react";
import { Radio } from "@xsolla/xui-radio";

export default function BasicRadio() {
  const [selected, setSelected] = React.useState("");

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      <Radio
        checked={selected === "option1"}
        onPress={() => setSelected("option1")}
        label="Option 1"
      />
      <Radio
        checked={selected === "option2"}
        onPress={() => setSelected("option2")}
        label="Option 2"
      />
      <Radio
        checked={selected === "option3"}
        onPress={() => setSelected("option3")}
        label="Option 3"
      />
    </div>
  );
}
```

### Radio with Description

```tsx
import * as React from "react";
import { Radio } from "@xsolla/xui-radio";

export default function RadioWithDescription() {
  const [plan, setPlan] = React.useState("basic");

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
      <Radio
        checked={plan === "basic"}
        onPress={() => setPlan("basic")}
        label="Basic Plan"
        description="Best for individuals, includes core features"
      />
      <Radio
        checked={plan === "pro"}
        onPress={() => setPlan("pro")}
        label="Pro Plan"
        description="Best for teams, includes advanced features"
      />
      <Radio
        checked={plan === "enterprise"}
        onPress={() => setPlan("enterprise")}
        label="Enterprise Plan"
        description="Custom solutions for large organizations"
      />
    </div>
  );
}
```

### Radio Sizes

```tsx
import * as React from "react";
import { Radio } from "@xsolla/xui-radio";

export default function RadioSizes() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
      <Radio size="sm" label="Small radio" checked />
      <Radio size="md" label="Medium radio (default)" checked />
      <Radio size="lg" label="Large radio" checked />
      <Radio size="xl" label="Extra large radio" checked />
    </div>
  );
}
```

## Anatomy

Import the component and use it directly:

```jsx
import { Radio } from "@xsolla/xui-radio";

<Radio
  checked={isSelected} // Whether this radio is selected
  onPress={handleSelect} // Click/tap handler
  onValueChange={handleChange} // Value change handler
  value="option1" // Value for RadioGroup context
  label="Option label" // Label text
  description="Help text" // Description below label
  errorLabel="Error text" // Error message
  state="default" // Visual state
  size="md" // Size variant
/>;
```

## Examples

### Error State

```tsx
import * as React from "react";
import { Radio } from "@xsolla/xui-radio";

export default function ErrorRadio() {
  return (
    <Radio
      checked={false}
      state="error"
      label="Select this option"
      errorLabel="Please make a selection"
    />
  );
}
```

### Disabled Radio

```tsx
import * as React from "react";
import { Radio } from "@xsolla/xui-radio";

export default function DisabledRadio() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      <Radio state="disable" label="Disabled unchecked" />
      <Radio state="disable" checked label="Disabled checked" />
    </div>
  );
}
```

## API Reference

### Radio

A single radio button component.

**Radio Props:**

| Prop            | Type                                           | Default     | Description                                                                                                   |
| :-------------- | :--------------------------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------ |
| `testID`        | `string`                                       | —           | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
| checked         | `boolean`                                      | `false`     | Whether the radio button is selected.                                                                         |
| value           | `string`                                       | -           | Value used when within RadioGroup.                                                                            |
| size            | `"sm" \| "md" \| "lg" \| "xl"`                 | `"md"`      | Size of the radio button.                                                                                     |
| state           | `"default" \| "hover" \| "disable" \| "error"` | `"default"` | Visual state of the radio.                                                                                    |
| label           | `string`                                       | -           | Label text displayed next to the radio.                                                                       |
| description     | `string`                                       | -           | Description text below the label.                                                                             |
| errorLabel      | `string`                                       | -           | Error message when state is "error".                                                                          |
| onPress         | `() => void`                                   | -           | Callback when the radio is pressed.                                                                           |
| onValueChange   | `(value: boolean) => void`                     | -           | Callback when checked state changes.                                                                          |
| aria-label      | `string`                                       | -           | Accessible label for screen readers.                                                                          |
| aria-labelledby | `string`                                       | -           | ID of element that labels this radio.                                                                         |

## Accessibility

- Uses `role="radio"` with proper ARIA attributes
- `aria-checked` reflects selection state
- Keyboard support (Space to select)
- Focus indicator follows WCAG guidelines
- Works with RadioGroup for proper group semantics
