Switch
Migration guide for Switch from HeroUI v2 to v3
Refer to the v3 Switch documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
Overview
The Switch component in HeroUI v3 has been redesigned with a compound component pattern, requiring explicit structure with Switch.Control and Switch.Thumb components.
Structure Changes
v2: Simple Structure
In v2, Switch used a simple structure with children as label:
import { Switch } from "@heroui/react";
<Switch>Enable notifications</Switch>v3: Compound Components
In v3, Switch requires compound components:
import { Switch, Label } from "@heroui/react";
<Switch>
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Enable notifications</Label>
</Switch>Key Changes
1. Component Structure
v2: Simple Switch with children as label
v3: Compound components (Switch.Control, Switch.Thumb) with Label component
2. Prop Changes
| v2 Prop | v3 Prop | Notes |
|---|---|---|
onValueChange | onChange | Renamed event handler |
label | - | Removed (use Label component) |
color | - | Removed (use Tailwind CSS) |
thumbIcon | - | Removed (use Switch.Icon inside Switch.Thumb) |
startContent | - | Removed (customize control) |
endContent | - | Removed (customize control) |
classNames | - | Use className props |
disableAnimation | - | Removed |
3. Removed Props
The following props are no longer available in v3:
label- UseLabelcomponent insteadcolor- Use Tailwind CSS classesthumbIcon- UseSwitch.Iconcomponent insideSwitch.ThumbstartContent,endContent- Customize control directlyclassNames- UseclassNameprops on individual componentsdisableAnimation- Animations handled differently
4. New Components
SwitchGroup- For grouping multiple switchesSwitch.Icon- For icons inside the thumb
Migration Examples
Basic Usage
import { Switch } from "@heroui/react";
export default function App() {
return <Switch defaultSelected aria-label="Automatic updates" />;
}import { Switch, Label } from "@heroui/react";
export default function App() {
return (
<Switch defaultSelected>
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Automatic updates</Label>
</Switch>
);
}Controlled Switch
import { useState } from "react";
const [isSelected, setIsSelected] = useState(true);
<Switch isSelected={isSelected} onValueChange={setIsSelected}>
Airplane mode
</Switch>import { useState } from "react";
const [isSelected, setIsSelected] = useState(true);
<Switch isSelected={isSelected} onChange={setIsSelected}>
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Airplane mode</Label>
</Switch>Without Label
<Switch defaultSelected aria-label="Automatic updates" /><Switch defaultSelected aria-label="Automatic updates">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
</Switch>With Thumb Icon
<Switch thumbIcon={<CheckIcon />}>Enable notifications</Switch><Switch>
<Switch.Control>
<Switch.Thumb>
<Switch.Icon>
<CheckIcon />
</Switch.Icon>
</Switch.Thumb>
</Switch.Control>
<Label>Enable notifications</Label>
</Switch>With Start/End Content
<Switch
startContent={<SunIcon />}
endContent={<MoonIcon />}
>
Dark mode
</Switch><Switch>
<Switch.Control className="flex items-center gap-2">
<SunIcon />
<Switch.Thumb />
<MoonIcon />
</Switch.Control>
<Label>Dark mode</Label>
</Switch>Sizes
<div className="flex gap-4">
<Switch size="sm">Small</Switch>
<Switch size="md">Medium</Switch>
<Switch size="lg">Large</Switch>
</div><div className="flex gap-4">
<Switch size="sm">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Small</Label>
</Switch>
<Switch size="md">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Medium</Label>
</Switch>
<Switch size="lg">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Large</Label>
</Switch>
</div>Colors
<Switch color="primary">Primary</Switch>
<Switch color="success">Success</Switch>
<Switch color="danger">Danger</Switch>{/* Use Tailwind CSS classes for colors */}
<Switch>
<Switch.Control className="data-[selected=true]:bg-accent">
<Switch.Thumb />
</Switch.Control>
<Label>Primary</Label>
</Switch>
<Switch>
<Switch.Control className="data-[selected=true]:bg-success">
<Switch.Thumb />
</Switch.Control>
<Label>Success</Label>
</Switch>
<Switch>
<Switch.Control className="data-[selected=true]:bg-danger">
<Switch.Thumb />
</Switch.Control>
<Label>Danger</Label>
</Switch>Disabled State
<Switch isDisabled>Disabled switch</Switch><Switch isDisabled>
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Disabled switch</Label>
</Switch>Custom Styling
<Switch
classNames={{
base: "custom-base",
wrapper: "custom-wrapper",
thumb: "custom-thumb"
}}
>
Custom switch
</Switch><Switch className="custom-base">
<Switch.Control className="custom-control">
<Switch.Thumb className="custom-thumb" />
</Switch.Control>
<Label>Custom switch</Label>
</Switch>Switch Group
{/* No built-in group component in v2 */}
<div className="flex flex-col gap-2">
<Switch name="notifications">Allow Notifications</Switch>
<Switch name="marketing">Marketing emails</Switch>
</div>import { SwitchGroup } from "@heroui/react";
<SwitchGroup>
<Switch name="notifications">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Allow Notifications</Label>
</Switch>
<Switch name="marketing">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Marketing emails</Label>
</Switch>
</SwitchGroup>Component Anatomy
The v3 Switch follows this structure:
Switch (Root)
├── Switch.Control
│ └── Switch.Thumb
│ └── Switch.Icon (optional)
└── Label (optional)For groups:
SwitchGroup
├── Switch
│ ├── Switch.Control
│ │ └── Switch.Thumb
│ └── Label
└── Switch
├── Switch.Control
│ └── Switch.Thumb
└── LabelImportant Notes
Event Handler
- v2:
onValueChangeprop - v3:
onChangeprop (same signature:(isSelected: boolean) => void)
Label Handling
- v2: Children were used as label
- v3: Use
Labelcomponent separately
Icons
- v2:
thumbIconprop for icon inside thumb,startContent/endContentfor icons outside - v3: Use
Switch.IconinsideSwitch.Thumbfor thumb icon, customizeSwitch.Controlfor start/end content
Breaking Changes Summary
- Component Structure: Must use compound components (
Switch.Control,Switch.Thumb) - Label Handling: Children no longer used as label - use
Labelcomponent - Event Handler:
onValueChange→onChange - Styling Props Removed:
color- use Tailwind CSS - Icon Props Removed:
thumbIcon,startContent,endContent- use components or customize directly - ClassNames Removed: Use
classNameprops on individual components - New Component:
SwitchGroupavailable for grouping switches
Tips for Migration
- Update structure: Wrap Switch content in
Switch.ControlandSwitch.Thumb - Add Label: Use
Labelcomponent for switch label - Update event handler: Change
onValueChangetoonChange - Update icons: Replace
thumbIconwithSwitch.IconinsideSwitch.Thumb - Update start/end content: Add icons directly to
Switch.Controlwith appropriate styling - Update colors: Use Tailwind CSS classes with
data-[selected=true]:prefix - Update styling: Replace
classNamesprop withclassNameprops on individual components - Use SwitchGroup: For grouping switches, use
SwitchGroupcomponent
Need Help?
For v3 Switch features and API:
- See the API Reference
- Check interactive examples
For community support: