Back to Heroui

Radio

apps/docs/content/docs/en/react/migration/(components)/radio.mdx

3.2.27.4 KB
Original Source
<Callout type="info"> Refer to the [v3 Radio 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, Radio used a simple structure with props:

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>
    </RadioGroup>
  );
}

In v3, Radio requires compound components:

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

export default function App() {
  return (
    <RadioGroup>
      <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>
    </RadioGroup>
  );
}

Key Changes

1. Component Structure

v2: Simple Radio with children as label
v3: Compound components: Radio.Content, Radio.Control, Radio.Indicator

2. Prop Changes

v2 Propv3 LocationNotes
onValueChangeonChangeRenamed event handler
label (on RadioGroup)Use Label component
description (on Radio)Use Description component as a sibling of Radio.Content
sizeRemoved (use Tailwind CSS)
colorRemoved (use Tailwind CSS)
classNamesUse className props on individual components
disableAnimationRemoved (animations handled differently)
variantNew prop on RadioGroup: "primary" (default) or "secondary" for lower emphasis styling
isReadOnlyNew prop on RadioGroup: prevents value changes while keeping the group focusable

Migration Examples

Form Validation

<Tabs items={["v2", "v3"]}> <Tab value="v2"> tsx <RadioGroup label="Select city"> <Radio value="london" description="Capital of England"> London </Radio> </RadioGroup> <RadioGroup isInvalid errorMessage="Please select an option" label="Select city" > <Radio value="london">London</Radio> </RadioGroup> </Tab> <Tab value="v3"> tsx import { Label, Description, FieldError } from "@heroui/react"; <RadioGroup> <Label>Select city</Label> <Radio value="london"> <Radio.Content> <Radio.Control> <Radio.Indicator /> </Radio.Control> London </Radio.Content> <Description>Capital of England</Description> </Radio> </RadioGroup> <RadioGroup isInvalid> <Label>Select city</Label> <Radio value="london"> <Radio.Content> <Radio.Control> <Radio.Indicator /> </Radio.Control> London </Radio.Content> </Radio> <FieldError>Please select an option</FieldError> </RadioGroup> </Tab> </Tabs>

Controlled

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

const [selected, setSelected] = useState("london");

<RadioGroup
  value={selected}
  onValueChange={setSelected}
>
  <Radio value="london">London</Radio>
  <Radio value="tokyo">Tokyo</Radio>
</RadioGroup>
```
</Tab> <Tab value="v3"> ```tsx import { useState } from "react";
const [selected, setSelected] = useState("london");

<RadioGroup value={selected} onChange={setSelected}>
  <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>

Horizontal Orientation

<Tabs items={["v2", "v3"]}> <Tab value="v2"> tsx <RadioGroup orientation="horizontal" label="Select city"> <Radio value="london">London</Radio> <Radio value="tokyo">Tokyo</Radio> </RadioGroup> </Tab> <Tab value="v3"> tsx <RadioGroup orientation="horizontal"> <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>

Variants

v3 introduces a variant prop on RadioGroup with "primary" (default) and "secondary" options:

tsx
<RadioGroup variant="primary">
  <Label>Select city</Label>
  <Radio value="london">
    <Radio.Content>
      <Radio.Control>
        <Radio.Indicator />
      </Radio.Control>
      London
    </Radio.Content>
  </Radio>
</RadioGroup>
<RadioGroup variant="secondary">
  <Label>Select city</Label>
  <Radio value="london">
    <Radio.Content>
      <Radio.Control>
        <Radio.Indicator />
      </Radio.Control>
      London
    </Radio.Content>
  </Radio>
</RadioGroup>

Read Only

v3 supports isReadOnly on RadioGroup, which prevents value changes while keeping the group focusable:

tsx
<RadioGroup isReadOnly defaultValue="london">
  <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>

Component Anatomy

The v3 Radio follows this structure:

RadioGroup (Root)
  ├── Label (optional)
  ├── Radio
  │   ├── Radio.Content (the clickable label)
  │   │   ├── Radio.Control
  │   │   │   └── Radio.Indicator
  │   │   └── Label
  │   └── Description (optional, sibling)
  └── FieldError (optional)

Summary

  1. Component Structure: Must use compound components (Radio.Content, Radio.Control, Radio.Indicator)
  2. Label Handling: label prop removed - use Label component
  3. Description Handling: description prop removed - use Description component as a sibling of Radio.Content
  4. Event Handler: onValueChangeonChange
  5. Styling Props Removed: size, color - use Tailwind CSS
  6. ClassNames Removed: Use className props on individual components
  7. Error Message: Use FieldError component instead of errorMessage prop
  8. New variant Prop: RadioGroup supports "primary" (default) and "secondary" for lower emphasis styling
  9. New isReadOnly Prop: RadioGroup supports isReadOnly to prevent value changes while keeping the group focusable