# RadioGroup

A set of radio buttons where only one option can be selected at a time.

## Import

```tsx
import { RadioGroup } from '@/heroui';
```

## Anatomy

```tsx
<RadioGroup>
  <RadioGroup.Item>
    <Label>...</Label>
    <Description>...</Description>
    <Radio>
      <Radio.Indicator>
        <Radio.IndicatorThumb />
      </Radio.Indicator>
    </Radio>
  </RadioGroup.Item>
  <FieldError>...</FieldError>
</RadioGroup>
```

- **RadioGroup**: Container that manages the selection state of radio items. Supports both horizontal and vertical orientations.
- **RadioGroup.Item**: Individual radio option within a RadioGroup. Must be used inside RadioGroup. Handles selection state and renders a default `<Radio />` indicator when text children are provided. Supports render function children to access state (`isSelected`, `isInvalid`, `isDisabled`).
- **Label**: Optional clickable text label for the radio option. Linked to the radio for accessibility. Use the [Label](../label/label.md) component directly.
- **Description**: Optional secondary text below the label. Provides additional context about the radio option. Use the [Description](../description/description.md) component directly.
- **Radio**: The [Radio](../radio/radio.md) component used inside `RadioGroup.Item` to render the radio indicator. Automatically detects the `RadioGroupItem` context and derives `isSelected`, `isDisabled`, `isInvalid`, and `variant` from it.
- **Radio.Indicator**: Optional container for the radio circle. Renders default thumb if no children provided. Manages the visual selection state. See [Radio](../radio/radio.md) for full API.
- **Radio.IndicatorThumb**: Optional inner circle that appears when selected. Animates scale based on selection. Can be replaced with custom content. See [Radio](../radio/radio.md) for full API.
- **FieldError**: Error message displayed when radio group is invalid. Shown with animation below the radio group content. Use the [FieldError](../field-error/field-error.md) component directly.

## Usage

### Basic Usage

RadioGroup with simple string children automatically renders title and indicator.

```tsx
<RadioGroup value={value} onValueChange={setValue}>
  <RadioGroup.Item value="option1">Option 1</RadioGroup.Item>
  <RadioGroup.Item value="option2">Option 2</RadioGroup.Item>
  <RadioGroup.Item value="option3">Option 3</RadioGroup.Item>
</RadioGroup>
```

### With Descriptions

Add descriptive text below each radio option for additional context.

```tsx
import { RadioGroup, Radio, Label, Description } from '@/heroui';
import { View } from 'react-native';

<RadioGroup value={value} onValueChange={setValue}>
  <RadioGroup.Item value="standard">
    <View>
      <Label>Standard Shipping</Label>
      <Description>Delivered in 5-7 business days</Description>
    </View>
    <Radio />
  </RadioGroup.Item>
  <RadioGroup.Item value="express">
    <View>
      <Label>Express Shipping</Label>
      <Description>Delivered in 2-3 business days</Description>
    </View>
    <Radio />
  </RadioGroup.Item>
</RadioGroup>;
```

### Custom Indicator

Replace the default indicator thumb with custom content using `Radio` sub-components.

```tsx
import { RadioGroup, Radio, Label } from '@/heroui';

<RadioGroup value={value} onValueChange={setValue}>
  <RadioGroup.Item value="custom">
    {({ isSelected }) => (
      <>
        <Label>Custom Option</Label>
        <Radio>
          <Radio.Indicator>
            {isSelected && (
              <Animated.View entering={FadeIn}>
                <Icon name="check" size={12} />
              </Animated.View>
            )}
          </Radio.Indicator>
        </Radio>
      </>
    )}
  </RadioGroup.Item>
</RadioGroup>;
```

### With Render Function

Use a render function on RadioGroup.Item to access state and customize the entire content.

```tsx
import { RadioGroup, Radio, Label } from '@/heroui';

<RadioGroup value={value} onValueChange={setValue}>
  <RadioGroup.Item value="option1">
    {({ isSelected, isInvalid, isDisabled }) => (
      <>
        <Label>Option 1</Label>
        <Radio>
          <Radio.Indicator>{isSelected && <CustomIcon />}</Radio.Indicator>
        </Radio>
      </>
    )}
  </RadioGroup.Item>
</RadioGroup>;
```

### With Error Message

Display validation errors below the radio group.

```tsx
import { RadioGroup, FieldError } from '@/heroui';

function RadioGroupWithError() {
  const [value, setValue] = React.useState<string | undefined>(undefined);

  return (
    <RadioGroup value={value} onValueChange={setValue} isInvalid={!value}>
      <RadioGroup.Item value="agree">I agree to the terms</RadioGroup.Item>
      <RadioGroup.Item value="disagree">I do not agree</RadioGroup.Item>
      <FieldError isInvalid={!value}>
        Please select an option to continue
      </FieldError>
    </RadioGroup>
  );
}
```

## Example

```tsx
import {
  Description,
  Label,
  Radio,
  RadioGroup,
  Separator,
  Surface,
} from '@/heroui';
import React from 'react';
import { View } from 'react-native';

export default function RadioGroupExample() {
  const [selection, setSelection] = React.useState('desc1');

  return (
    <Surface className="w-full">
      <RadioGroup value={selection} onValueChange={setSelection}>
        <RadioGroup.Item value="desc1">
          <View>
            <Label>Standard Shipping</Label>
            <Description>Delivered in 5-7 business days</Description>
          </View>
          <Radio />
        </RadioGroup.Item>
        <Separator className="my-1" />
        <RadioGroup.Item value="desc2">
          <View>
            <Label>Express Shipping</Label>
            <Description>Delivered in 2-3 business days</Description>
          </View>
          <Radio />
        </RadioGroup.Item>
        <Separator className="my-1" />
        <RadioGroup.Item value="desc3">
          <View>
            <Label>Overnight Shipping</Label>
            <Description>Delivered next business day</Description>
          </View>
          <Radio />
        </RadioGroup.Item>
      </RadioGroup>
    </Surface>
  );
}
```

You can find more examples in the [GitHub repository](<https://github.com/heroui-inc/heroui-native/blob/rc/example/src/app/(home)/components/radio-group.tsx>).

## API Reference

### RadioGroup

| prop            | type                         | default     | description                                                                               |
| --------------- | ---------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
| `children`      | `React.ReactNode`            | `undefined` | Radio group content                                                                       |
| `value`         | `string \| undefined`        | `undefined` | The currently selected value of the radio group                                           |
| `onValueChange` | `(val: string) => void`      | `undefined` | Callback fired when the selected value changes                                            |
| `isDisabled`    | `boolean`                    | `false`     | Whether the entire radio group is disabled                                                |
| `isInvalid`     | `boolean`                    | `false`     | Whether the radio group is invalid                                                        |
| `variant`       | `'primary' \| 'secondary'`   | `undefined` | Variant style for the radio group (inherited by items if not set on item)                 |
| `animation`     | `"disable-all" \| undefined` | `undefined` | Animation configuration. Use `"disable-all"` to disable all animations including children |
| `className`     | `string`                     | `undefined` | Custom class name                                                                         |
| `...ViewProps`  | `ViewProps`                  | -           | All standard React Native View props are supported                                        |

### RadioGroup.Item

| prop                | type                                                                         | default     | description                                                               |
| ------------------- | ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `children`          | `React.ReactNode \| ((props: RadioGroupItemRenderProps) => React.ReactNode)` | `undefined` | Radio item content or render function to customize the radio item         |
| `value`             | `string`                                                                     | `undefined` | The value associated with this radio item                                 |
| `isDisabled`        | `boolean`                                                                    | `false`     | Whether this specific radio item is disabled                              |
| `isInvalid`         | `boolean`                                                                    | `false`     | Whether the radio item is invalid                                         |
| `variant`           | `'primary' \| 'secondary'`                                                   | `'primary'` | Variant style for the radio item                                          |
| `hitSlop`           | `number`                                                                     | `6`         | Hit slop for the pressable area                                           |
| `className`         | `string`                                                                     | `undefined` | Custom class name                                                         |
| `...PressableProps` | `PressableProps`                                                             | -           | All standard React Native Pressable props are supported (except disabled) |

#### RadioGroupItemRenderProps

| prop         | type      | description                        |
| ------------ | --------- | ---------------------------------- |
| `isSelected` | `boolean` | Whether the radio item is selected |
| `isInvalid`  | `boolean` | Whether the radio item is invalid  |
| `isDisabled` | `boolean` | Whether the radio item is disabled |

### Radio (inside RadioGroup.Item)

The [Radio](../radio/radio.md) component is used inside `RadioGroup.Item` to render the radio indicator. When placed inside a `RadioGroup.Item`, the Radio component automatically detects the `RadioGroupItem` context and derives `isSelected`, `isDisabled`, `isInvalid`, and `variant` from it — no manual prop passing is needed.

Use `<Radio />` for the default indicator, or compose with `Radio.Indicator` and `Radio.IndicatorThumb` for custom styling.

**Note:** For complete Radio prop documentation (including `Radio.Indicator` and `Radio.IndicatorThumb`), see the [Radio component documentation](../radio/radio.md).

**Note:** For labels, descriptions, and error messages, use the base components directly:

- Use [Label](../label/label.md) component for labels
- Use [Description](../description/description.md) component for descriptions
- Use [FieldError](../field-error/field-error.md) component for error messages

## Hooks

### useRadioGroup

**Returns:**

| Property        | Type                       | Description                                    |
| --------------- | -------------------------- | ---------------------------------------------- |
| `value`         | `string \| undefined`      | Currently selected value                       |
| `isDisabled`    | `boolean`                  | Whether the radio group is disabled            |
| `isInvalid`     | `boolean`                  | Whether the radio group is in an invalid state |
| `variant`       | `'primary' \| 'secondary'` | Variant style for the radio group              |
| `onValueChange` | `(value: string) => void`  | Function to change the selected value          |

### useRadioGroupItem

**Returns:**

| Property           | Type                                           | Description                                                             |
| ------------------ | ---------------------------------------------- | ----------------------------------------------------------------------- |
| `isSelected`       | `boolean`                                      | Whether the radio item is selected                                      |
| `isDisabled`       | `boolean \| undefined`                         | Whether the radio item is disabled                                      |
| `isInvalid`        | `boolean \| undefined`                         | Whether the radio item is invalid                                       |
| `variant`          | `'primary' \| 'secondary' \| undefined`        | Variant style for the radio item                                        |
| `onSelectedChange` | `((isSelected: boolean) => void) \| undefined` | Callback to change the selection state (selects this item in the group) |
