Switch installs into your project as a file you own. It takes the same props as Ant Design's Switch and adds two of its own: color for the on track and shape for its corners, marked antuikit in the API table below.
It also shows its hover state while a wrapping <label> is hovered, so a whole settings row can be the click target (see Wrapping it in a label). className goes through cn(), so conflicting Tailwind classes in your own string resolve to the last one. switchVariants is exported, so another element can take the same shape classes.
Install
npx antuikit@latest init
npx antuikit@latest add switch
The first command sets up AntuikitProvider and the theme, and the second adds this component with antuikit-base, which the label hover needs. Switch needs no icon pack.
Import
Import from @/components/ui/switch, the file the install added to your project, never from antd.
import { Switch } from "@/components/ui/switch"
The axes
color paints the on track, its hover and its focus ring. It takes three kinds of value:
primary (the default), the theme's colorPrimary.
success, warning and error, the status colors, named as Tag and Alert name them.
antd's presets (blue, green, gold and the rest) or a palette from your theme (the default theme adds amber, emerald, teal, sky, indigo, violet, fuchsia, rose and grays like slate and zinc), with a lighter shade on hover and for the focus ring. A gray palette, a CSS color or an unknown name falls back to primary.
1
<Switch defaultChecked />
2
<Switch color="success" defaultChecked />
3
<Switch color="error" defaultChecked />
4
<Switch color="emerald" defaultChecked />
shape sets the track's corners, and the knob follows them:
square: the theme's small radius, borderRadiusSM.
squircle: a superellipse a little rounder than square. Browsers without corner-shape support draw it as square.
default: the pill.
1
<Switch shape="square" defaultChecked />
2
<Switch shape="squircle" defaultChecked />
size takes medium (the default) and small. There is no large. middle and default still work as older names for medium, and default logs a warning in development. Compact mode makes both sizes smaller.
1
<Switch defaultChecked />
2
<Switch size="small" defaultChecked />
Flags
checked with onChange controls the switch, and defaultChecked lets it manage itself. Anything that has to confirm, guard or wait for the flip needs the controlled form.
value and defaultValue also work, for form libraries that bind value. When both spellings are set, checked wins.
disabled sets the native attribute on the button. A Form or ConfigProvider with disabled disables every Switch inside it.
loading disables the switch while it spins, so a click cannot race a request in flight.
autoFocus passes through to the button.
Put it in a Form with valuePropName="checked".Form.Item binds value by default, so without it the field always reads as off and never reports a change.
The loading spinner is Ant Design's own. There is no prop or ConfigProvider setting to replace it, which is why Switch needs no icon pack. To hide it and keep a bare knob, pass classNames={{ indicator: "[&_.anticon]:hidden" }}.
Events
onChange(checked, event) is the one to use. It fires for a click and for the arrow keys, and not at all while the switch is disabled or loading.
ArrowLeft and ArrowRight set off and on rather than toggling, and they call onChange even when the value does not change. Check that it changed before writing to a server.
onClick(checked, event) takes the new value first, not the event. It only fires for a real click, so the arrow keys skip it while Space and Enter do not. Keep the work in onChange.
Wrapping it in a label
Wrap it in a <label> to make its text a click target. A click anywhere in the label toggles the switch, and hovering the label shows the switch's hover color, in its own color. The label gets a pointer cursor, except while the switch is disabled or loading.
A label only takes inline content, so use <Flex component="span"> for the column inside it.
Point aria-labelledby at the title and aria-describedby at the description, or the switch's name becomes the whole label text.
Anything else clickable in the label, like a help icon or a link, needs preventDefault() in its click handler, or reading the help flips the setting.
Without a label around it, the hover classes do nothing.
Styling
classNames and styles take the same three keys, as an object or a function of { props } that returns one. The plain className lands on the root.
1
<Switch
2
classNames={{
3
root: "…",
4
content: "…",
5
indicator: "…",
6
}}
7
/>
root is the button itself, so it sets the track's width: w-xxl makes it wider. For the corners, use shape, which moves the knob too.
content is on both text spans in the track, the checked one and the unchecked one, so a class there applies in both states.
indicator is the handle, and the white knob is drawn on its ::before. Use a before: class, like before:rounded-xs, to change the knob.
Prefer theme classes like rounded-xs and w-xxl over fixed values like before:rounded-[4px], so the switch follows the theme when its radius or sizes change.
For the on color, use color rather than a class. A [&.ant-switch-checked]:bg-* class paints the track only, and leaves the hover, the focus ring and the loading spinner in the primary color.
A Tailwind class on one of these keys overrides the default style without !important. Setting a component token's CSS variable as a class, like [--ant-switch-handle-bg:…], has no effect, so style the part here or change the token in your theme.
API Reference
Switch
Switch's props. Rows marked antuikit in the Version column are added by the kit.