---
title: RadioGroup
description: Migration guide for RadioGroup from HeroUI v2 to v3
---

<Callout type="info">
  Refer to the [v3 RadioGroup documentation](/docs/react/components/radio-group) for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
</Callout>

## Structure Changes

In v2, `RadioGroup` used a `label` prop:

```tsx
import { RadioGroup, Radio } from "@heroui/react";

export default function App() {
  return (
    <RadioGroup label="Select city">
      <Radio value="london">London</Radio>
      <Radio value="tokyo" description="Capital of Japan">Tokyo</Radio>
      <Radio value="paris">Paris</Radio>
    </RadioGroup>
  );
}
```

In v3, `RadioGroup` uses `Label` component and works with compound Radio structure:

```tsx
import { RadioGroup, Radio, Label, Description } from "@heroui/react";

export default function App() {
  return (
    <RadioGroup name="city">
      <Label>Select city</Label>
      <Radio value="london">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          London
        </Radio.Content>
      </Radio>
      <Radio value="tokyo">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Tokyo
        </Radio.Content>
        <Description>Capital of Japan</Description>
      </Radio>
      <Radio value="paris">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Paris
        </Radio.Content>
      </Radio>
    </RadioGroup>
  );
}
```

## Key Changes

### 1. Label Prop → Label Component

**v2:** Used `label` prop on `RadioGroup`  
**v3:** Use `Label` component as a child of `RadioGroup`

### 2. Radio Structure

**v2:** Simple Radio components with children as labels  
**v3:** Compound Radio components with `Radio.Content`, `Radio.Control`, and `Radio.Indicator`

### 3. Description Handling

**v2:** Used `description` prop on individual `Radio` components  
**v3:** Use `Description` component as a sibling of `Radio.Content`

### 4. Event Handler

**v2:** Used `onValueChange` prop  
**v3:** Uses `onChange` prop (from React Aria Components)

### 5. Name Prop

**v3:** `name` prop is required for form integration

### 6. Variant Support

**v3:** New `variant` prop: `"primary"` (default) or `"secondary"` for lower emphasis styling suitable for Surface components

### 7. Read Only Support

**v3:** New `isReadOnly` prop prevents value changes while keeping the group focusable

## Migration Examples

### RadioGroup with Descriptions

<Tabs items={["v2", "v3"]}>
  <Tab value="v2">
    ```tsx
    <RadioGroup label="Select plan">
      <Radio value="basic" description="Basic features">Basic</Radio>
      <Radio value="pro" description="All features">Pro</Radio>
    </RadioGroup>
    ```
  </Tab>
  <Tab value="v3">
    ```tsx
    import { RadioGroup, Radio, Label, Description } from "@heroui/react";

    <RadioGroup name="plan">
      <Label>Select plan</Label>
      <Radio value="basic">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Basic
        </Radio.Content>
        <Description>Basic features</Description>
      </Radio>
      <Radio value="pro">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Pro
        </Radio.Content>
        <Description>All features</Description>
      </Radio>
    </RadioGroup>
    ```
  </Tab>
</Tabs>

### Variants

<Tabs items={["v2", "v3"]}>
  <Tab value="v2">
    ```tsx
    {/* v2 did not have variant support */}
    <RadioGroup label="Select plan">
      <Radio value="basic">Basic</Radio>
      <Radio value="pro">Pro</Radio>
    </RadioGroup>
    ```
  </Tab>
  <Tab value="v3">
    ```tsx
    import { RadioGroup, Radio, Label } from "@heroui/react";

    {/* Primary variant (default) */}
    <RadioGroup variant="primary" name="plan">
      <Label>Select plan</Label>
      <Radio value="basic">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Basic
        </Radio.Content>
      </Radio>
    </RadioGroup>

    {/* Secondary variant - lower emphasis, suitable for Surface components */}
    <RadioGroup variant="secondary" name="plan">
      <Label>Select plan</Label>
      <Radio value="basic">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Basic
        </Radio.Content>
      </Radio>
    </RadioGroup>
    ```
  </Tab>
</Tabs>

### Read Only

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

{/* Prevents value changes while keeping the group focusable */}
<RadioGroup isReadOnly defaultValue="basic" name="plan">
  <Label>Select plan</Label>
  <Radio value="basic">
    <Radio.Content>
      <Radio.Control>
        <Radio.Indicator />
      </Radio.Control>
      Basic
    </Radio.Content>
  </Radio>
  <Radio value="pro">
    <Radio.Content>
      <Radio.Control>
        <Radio.Indicator />
      </Radio.Control>
      Pro
    </Radio.Content>
  </Radio>
</RadioGroup>
```

### Controlled RadioGroup

<Tabs items={["v2", "v3"]}>
  <Tab value="v2">
    ```tsx
    import { useState } from "react";
    import { RadioGroup, Radio } from "@heroui/react";

    const [value, setValue] = useState("london");

    <RadioGroup value={value} onValueChange={setValue} label="Select city">
      <Radio value="london">London</Radio>
      <Radio value="tokyo">Tokyo</Radio>
    </RadioGroup>
    ```
  </Tab>
  <Tab value="v3">
    ```tsx
    import { useState } from "react";
    import { RadioGroup, Radio, Label } from "@heroui/react";

    const [value, setValue] = useState("london");

    <RadioGroup name="city" value={value} onChange={setValue}>
      <Label>Select city</Label>
      <Radio value="london">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          London
        </Radio.Content>
      </Radio>
      <Radio value="tokyo">
        <Radio.Content>
          <Radio.Control>
            <Radio.Indicator />
          </Radio.Control>
          Tokyo
        </Radio.Content>
      </Radio>
    </RadioGroup>
    ```
  </Tab>
</Tabs>

## Summary

- Replace `label` prop with `Label` component as child
- Update Radio children to use compound component structure
- Replace `description` prop on Radio with `Description` component as a sibling of `Radio.Content`
- Change `onValueChange` to `onChange`
- Add `name` prop for form integration
- New `variant` prop: `"primary"` (default) or `"secondary"` for lower emphasis styling
- New `isReadOnly` prop: prevents value changes while keeping the group focusable
- Better accessibility through React Aria Components
