# Radio Group

A cross-platform React radio group component that manages single selection across multiple radio buttons. Provides context to child Radio components for coordinated selection.

## Installation

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

## Demo

### Basic Radio Group

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

export default function BasicRadioGroup() {
  const [value, setValue] = React.useState("option1");

  return (
    <RadioGroup value={value} onChange={setValue}>
      <Radio value="option1" label="Option 1" />
      <Radio value="option2" label="Option 2" />
      <Radio value="option3" label="Option 3" />
    </RadioGroup>
  );
}
```

### Horizontal Layout

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

export default function HorizontalRadioGroup() {
  const [size, setSize] = React.useState("md");

  return (
    <RadioGroup value={size} onChange={setSize} flexDirection="row" gap={24}>
      <Radio value="sm" label="Small" />
      <Radio value="md" label="Medium" />
      <Radio value="lg" label="Large" />
    </RadioGroup>
  );
}
```

### Radio Group with Descriptions

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

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

  return (
    <RadioGroup value={plan} onChange={setPlan} gap={16}>
      <Radio
        value="starter"
        label="Starter"
        description="$9/month - Best for personal projects"
      />
      <Radio
        value="professional"
        label="Professional"
        description="$29/month - Best for small teams"
      />
      <Radio
        value="enterprise"
        label="Enterprise"
        description="Custom pricing - For large organizations"
      />
    </RadioGroup>
  );
}
```

### Disabled Radio Group

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

export default function DisabledRadioGroup() {
  return (
    <RadioGroup value="option1" disabled>
      <Radio value="option1" label="Option 1" />
      <Radio value="option2" label="Option 2" />
      <Radio value="option3" label="Option 3" />
    </RadioGroup>
  );
}
```

## Anatomy

Import the components and compose them:

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

<RadioGroup
  value={selectedValue} // Currently selected value
  onChange={handleChange} // Selection change handler
  size="md" // Size for all child radios
  disabled={false} // Disable all radios
  flexDirection="column" // Layout direction
  gap={12} // Gap between items
>
  <Radio value="a" label="Option A" />
  <Radio value="b" label="Option B" />
  <Radio value="c" label="Option C" />
</RadioGroup>;
```

## Examples

### Form Integration

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

export default function FormRadioGroup() {
  const [shipping, setShipping] = React.useState("");
  const [error, setError] = React.useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!shipping) {
      setError("Please select a shipping method");
      return;
    }
    console.log("Selected shipping:", shipping);
  };

  return (
    <form onSubmit={handleSubmit}>
      <h3 id="shipping-label">Select Shipping Method</h3>
      <RadioGroup
        value={shipping}
        onChange={(v) => {
          setShipping(v);
          setError("");
        }}
        aria-labelledby="shipping-label"
        aria-describedby={error ? "shipping-error" : undefined}
      >
        <Radio
          value="standard"
          label="Standard Shipping"
          description="5-7 business days - Free"
        />
        <Radio
          value="express"
          label="Express Shipping"
          description="2-3 business days - $9.99"
        />
        <Radio
          value="overnight"
          label="Overnight Shipping"
          description="Next business day - $24.99"
        />
      </RadioGroup>
      {error && (
        <p id="shipping-error" role="alert" style={{ color: "red" }}>
          {error}
        </p>
      )}
      <Button type="submit" style={{ marginTop: 16 }}>
        Continue
      </Button>
    </form>
  );
}
```

### Different Sizes

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

export default function RadioGroupSizes() {
  const [value, setValue] = React.useState("a");

  return (
    <div style={{ display: "flex", gap: 48 }}>
      <div>
        <h4>Small</h4>
        <RadioGroup value={value} onChange={setValue} size="sm">
          <Radio value="a" label="Option A" />
          <Radio value="b" label="Option B" />
        </RadioGroup>
      </div>
      <div>
        <h4>Large</h4>
        <RadioGroup value={value} onChange={setValue} size="lg">
          <Radio value="a" label="Option A" />
          <Radio value="b" label="Option B" />
        </RadioGroup>
      </div>
    </div>
  );
}
```

## API Reference

### RadioGroup

Container component that provides selection context to Radio children.

**RadioGroup 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`. |
| children      | `ReactNode`                    | -          | **Required.** Radio components to group.                                                                      |
| value         | `string`                       | -          | Currently selected value.                                                                                     |
| onChange      | `(value: string) => void`      | -          | Callback when selection changes.                                                                              |
| size          | `"sm" \| "md" \| "lg" \| "xl"` | `"md"`     | Size applied to all child Radio components.                                                                   |
| disabled      | `boolean`                      | `false`    | Whether all radios are disabled.                                                                              |
| flexDirection | `"row" \| "column"`            | `"column"` | Layout direction of the group.                                                                                |
| gap           | `number`                       | `12`       | Gap between radio items in pixels.                                                                            |

### RadioGroup Context

RadioGroup provides context to child Radio components:

```typescript
interface RadioGroupContextProps {
  value?: string; // Currently selected value
  onChange?: (value: string) => void; // Selection handler
  size?: "sm" | "md" | "lg" | "xl"; // Size for radios
  disabled?: boolean; // Disabled state
}
```

Child Radio components automatically:

- Sync their checked state with the group value
- Call the group's onChange when selected
- Inherit size and disabled props from the group

## Accessibility

- RadioGroup provides proper grouping semantics
- Only one radio can be selected at a time
- Arrow keys navigate between options when focused
- Tab key moves focus to/from the group
- Disabled state properly communicated to all children
