Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
Enabled
import { useState } from "react";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
export const SwitchDemo = () => {
const [notifications, setNotifications] = useState(true);
return (
<div className="flex flex-col gap-6">
{/* Basic */}
<div className="flex items-center gap-2">
<Switch id="sw-basic" defaultChecked sounds />
<Label htmlFor="sw-basic">Airplane mode</Label>
</div>
{/* Controlled with status */}
<div className="flex items-center justify-between rounded-lg border p-4">
<div className="flex flex-col gap-0.5">
<Label htmlFor="sw-notifications" className="text-sm font-medium">Push notifications</Label>
<span className="text-muted-foreground text-xs">{notifications ? "Enabled" : "Disabled"}</span>
</div>
<Switch
id="sw-notifications"
checked={notifications}
onCheckedChange={setNotifications}
sounds
/>
</div>
{/* Group */}
<div className="flex flex-col gap-3 rounded-lg border p-4">
{[
{ defaultChecked: true, id: "sw-email", label: "Email digest" },
{ defaultChecked: false, id: "sw-sms", label: "SMS alerts" },
{ defaultChecked: true, id: "sw-slack", label: "Slack messages" },
].map(({ id, label, defaultChecked }) => (
<div key={id} className="flex items-center justify-between">
<Label htmlFor={id}>{label}</Label>
<Switch id={id} defaultChecked={defaultChecked} sounds />
</div>
))}
</div>
{/* Disabled states */}
<div className="flex items-center gap-6">
<div className="flex items-center gap-2">
<Switch id="sw-dis-off" disabled />
<Label htmlFor="sw-dis-off" className="text-muted-foreground">Off (disabled)</Label>
</div>
<div className="flex items-center gap-2">
<Switch id="sw-dis-on" disabled defaultChecked />
<Label htmlFor="sw-dis-on" className="text-muted-foreground">On (disabled)</Label>
</div>
</div>
</div>
);
};With label
Pair with Label using a shared id / htmlFor for accessible click target.
<div className="flex items-center gap-2">
<Switch id="airplane" defaultChecked />
<Label htmlFor="airplane">Airplane mode</Label>
</div>Controlled
const [checked, setChecked] = useState(false);
<Switch checked={checked} onCheckedChange={setChecked} />Settings row pattern
<div className="flex items-center justify-between rounded-lg border p-4">
<div className="flex flex-col gap-0.5">
<Label htmlFor="notifs" className="font-medium">Push notifications</Label>
<span className="text-muted-foreground text-xs">Receive alerts on your device</span>
</div>
<Switch id="notifs" defaultChecked />
</div>With sounds
Pass sounds to play toggleOn when switched on and toggleOff when switched off.
<Switch sounds />Props
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled checked state |
defaultChecked | boolean | false | Uncontrolled initial state |
onCheckedChange | (checked: boolean) => void | — | Callback on state change |
disabled | boolean | false | Disables interaction |
sounds | boolean | false | Plays toggleOn / toggleOff audio |
Usage
import { Switch } from "@/components/ui/switch";
<Switch defaultChecked onCheckedChange={(v) => console.log(v)} />Specs
# Mint — Switch Specs
## Component
- name: switch
- file: registry/mint/switch.tsx
- installs to: components/ui/switch.tsx
- dependencies: radix-ui
- registryDependencies: none
## What is it
A binary toggle control built on Radix Switch.Root + Switch.Thumb. Use it to
represent an on/off setting that takes effect immediately without a form submit.
Prefer Switch over a Checkbox when the action is instant; do not use it when
the user must confirm the change before it applies.
## Visual identity
Pill-shaped track (rounded-full) transitions from a muted input colour when
unchecked to the theme primary when checked. A small circular thumb slides
across with a smooth CSS transition, giving clear directional feedback.
Mint's 1.25rem radius base keeps the track corners proportionate.
## Design tokens
--input: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%) — track colour when unchecked
--primary: oklch(0.5 0.14 155) / oklch(0.62 0.15 155) — track colour when checked
--background: oklch(1 0 0) / oklch(0.145 0 0) — thumb fill
--ring: oklch(0.5 0.14 155) / oklch(0.62 0.15 155) — focus ring colour
--destructive: oklch(0.55 0.25 15) / oklch(0.704 0.191 22.216) — invalid border
## Sub-components
- Switch → root toggle (SwitchPrimitive.Root); renders track, handles interaction
- Switch.Thumb → sliding circle (SwitchPrimitive.Thumb); moves on state change
## States
- unchecked: track is --input (soft translucent green)
- checked: track becomes --primary; thumb translates 1rem (translate-x-4)
- focus-visible: 3px ring in --ring/50, border switches to --ring
- disabled: opacity-50, cursor-not-allowed, pointer-events blocked
- aria-invalid: destructive/20 ring (light) / destructive/40 ring (dark) + destructive border
## Conventions
- Always pair with a Label via matching id / htmlFor for accessible click target
- Place label after the switch in DOM order (switch left, label right) to match natural reading flow
- In settings-row layouts use justify-between with the switch on the trailing side
- sounds / haptic: GIN Design exclusive — plays toggleOn audio when switched on and toggleOff when switched off; pass sounds prop to enable
- Sub-components expose data-slot="switch" and data-slot="switch-thumb" for CSS targeting
- No variants defined — visual appearance is controlled entirely by theme tokensInstallation
$ npx shadcn add \https://gin-design.vercel.app/switch