# RadioGroup
**Category**: native
**URL**: https://www.heroui.com/docs/native/components/radio-group
**Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/native/components/(forms)/radio-group.mdx
> A set of radio buttons where only one option can be selected at a time.
***
## Import
```tsx
import { RadioGroup } from 'heroui-native';
```
## Anatomy
```tsx
......
```
- **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 `` 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) component directly.
- **Description**: Optional secondary text below the label. Provides additional context about the radio option. Use the [Description](./description) component directly.
- **Radio**: The [Radio](./radio) 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) 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) 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) component directly.
## Usage
### Basic Usage
RadioGroup with simple string children automatically renders title and indicator.
```tsx
Option 1Option 2Option 3
```
### With Descriptions
Add descriptive text below each radio option for additional context.
```tsx
import { RadioGroup, Radio, Label, Description } from 'heroui-native';
import { View } from 'react-native';
Delivered in 5-7 business daysDelivered in 2-3 business days;
```
### Custom Indicator
Replace the default indicator thumb with custom content using `Radio` sub-components.
```tsx
import { RadioGroup, Radio, Label } from 'heroui-native';
{({ isSelected }) => (
<>
{isSelected && (
)}
>
)}
;
```
### 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-native';
{({ isSelected, isInvalid, isDisabled }) => (
<>
{isSelected && }
>
)}
;
```
### With Error Message
Display validation errors below the radio group.
```tsx
import { RadioGroup, FieldError } from 'heroui-native';
function RadioGroupWithError() {
const [value, setValue] = React.useState(undefined);
return (
I agree to the termsI do not agree
Please select an option to continue
);
}
```
## Example
```tsx
import {
Description,
Label,
Radio,
RadioGroup,
Separator,
Surface,
} from 'heroui-native';
import React from 'react';
import { View } from 'react-native';
export default function RadioGroupExample() {
const [selection, setSelection] = React.useState('desc1');
return (
Delivered in 5-7 business daysDelivered in 2-3 business daysDelivered next business day
);
}
```
You can find more examples in the [GitHub repository]().
## 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` 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 `` for the default indicator, or compose with `Radio.Indicator` and `Radio.IndicatorThumb` for custom styling.
| prop | type | default | description |
| ------------------- | ------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `children` | `React.ReactNode \| ((props: RadioRenderProps) => React.ReactNode)` | `undefined` | Child elements or render function to customize the radio |
| `variant` | `'primary' \| 'secondary'` | `'primary'` | Variant style for the radio |
| `isSelected` | `boolean` | `undefined` | Whether the radio is currently selected |
| `isDisabled` | `boolean` | `undefined` | Whether the radio is disabled and cannot be interacted with |
| `isInvalid` | `boolean` | `false` | Whether the radio is invalid (shows danger color) |
| `className` | `string` | `undefined` | Additional CSS classes to apply |
| `animation` | `RadioRootAnimation` | - | Animation configuration for radio |
| `onSelectedChange` | `(isSelected: boolean) => void` | `undefined` | Callback fired when the radio selection state changes |
| `...PressableProps` | `PressableProps` | - | All standard React Native Pressable props are supported (except disabled) |
#### RadioRenderProps
| prop | type | description |
| ------------ | --------- | ----------------------------- |
| `isSelected` | `boolean` | Whether the radio is selected |
| `isDisabled` | `boolean` | Whether the radio is disabled |
| `isInvalid` | `boolean` | Whether the radio is invalid |
#### RadioRootAnimation
Animation configuration for radio root component. Can be:
- `"disable-all"`: Disable all animations including children (Indicator, IndicatorThumb)
- `undefined`: Use default animations
### Radio.Indicator
| prop | type | default | description |
| ---------------------- | -------------------------- | ----------- | ------------------------------------------------ |
| `children` | `React.ReactNode` | `undefined` | Content for the radio indicator |
| `className` | `string` | `undefined` | Additional CSS classes for the indicator |
| `...AnimatedViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
### Radio.IndicatorThumb
| prop | type | default | description |
| ----------------------- | ------------------------------ | ----------- | ------------------------------------------------------------ |
| `className` | `string` | `undefined` | Additional CSS classes for the thumb |
| `animation` | `RadioIndicatorThumbAnimation` | - | Animation configuration for the thumb |
| `isAnimatedStyleActive` | `boolean` | `true` | Whether animated styles (react-native-reanimated) are active |
| `...AnimatedViewProps` | `AnimatedProps` | - | All Reanimated Animated.View props are supported |
#### RadioIndicatorThumbAnimation
Animation configuration for radio indicator thumb component. Can be:
- `false` or `"disabled"`: Disable all animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration
| prop | type | default | description |
| -------------------- | ----------------------- | ---------------------------------------------------- | ----------------------------------------------- |
| `state` | `'disabled' \| boolean` | - | Disable animations while customizing properties |
| `scale.value` | `[number, number]` | `[1.5, 1]` | Scale values [unselected, selected] |
| `scale.timingConfig` | `WithTimingConfig` | `{ duration: 300, easing: Easing.out(Easing.ease) }` | Animation timing configuration |
**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) |