Pro--% off in--d : --h : --m : --s
HeroUI

RadioGroup

Migration guide for RadioGroup from HeroUI v2 to v3

Refer to the v3 RadioGroup documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.

Structure Changes

In v2, RadioGroup used a label prop:

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:

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

export default function App() {
  return (
    <RadioGroup name="city">
      <Label>Select city</Label>
      <Radio value="london">
        <Radio.Control>
          <Radio.Indicator />
        </Radio.Control>
        <Radio.Content>
          <Label>London</Label>
        </Radio.Content>
      </Radio>
      <Radio value="tokyo">
        <Radio.Control>
          <Radio.Indicator />
        </Radio.Control>
        <Radio.Content>
          <Label>Tokyo</Label>
          <Description>Capital of Japan</Description>
        </Radio.Content>
      </Radio>
      <Radio value="paris">
        <Radio.Control>
          <Radio.Indicator />
        </Radio.Control>
        <Radio.Content>
          <Label>Paris</Label>
        </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.Control, Radio.Indicator, and Radio.Content

3. Description Handling

v2: Used description prop on individual Radio components
v3: Use Description component inside 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

<RadioGroup label="Select plan">
  <Radio value="basic" description="Basic features">Basic</Radio>
  <Radio value="pro" description="All features">Pro</Radio>
</RadioGroup>
import { RadioGroup, Radio, Label, Description } from "@heroui/react";

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

Variants

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

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

Read Only

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.Control>
      <Radio.Indicator />
    </Radio.Control>
    <Radio.Content>
      <Label>Basic</Label>
    </Radio.Content>
  </Radio>
  <Radio value="pro">
    <Radio.Control>
      <Radio.Indicator />
    </Radio.Control>
    <Radio.Content>
      <Label>Pro</Label>
    </Radio.Content>
  </Radio>
</RadioGroup>

Controlled RadioGroup

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>
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.Control>
      <Radio.Indicator />
    </Radio.Control>
    <Radio.Content>
      <Label>London</Label>
    </Radio.Content>
  </Radio>
  <Radio value="tokyo">
    <Radio.Control>
      <Radio.Indicator />
    </Radio.Control>
    <Radio.Content>
      <Label>Tokyo</Label>
    </Radio.Content>
  </Radio>
</RadioGroup>

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 inside 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

On this page