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
labelprop withLabelcomponent as child - Update Radio children to use compound component structure
- Replace
descriptionprop on Radio withDescriptioncomponent insideRadio.Content - Change
onValueChangetoonChange - Add
nameprop for form integration - New
variantprop:"primary"(default) or"secondary"for lower emphasis styling - New
isReadOnlyprop: prevents value changes while keeping the group focusable - Better accessibility through React Aria Components