Switch
A toggle control for binary choices with smooth animations.
Overview
The Switch component provides a toggle control for binary choices, offering a more visually distinct alternative to checkboxes for on/off or enable/disable settings. Built on Base UI primitives, it offers full keyboard navigation and accessibility features.
Usage
import { Switch } from "@tilt-legal/cubitt-components/primitives";<Switch />With Label
Always associate switches with descriptive labels for better accessibility and user experience:
<Label orientation="horizontal">
<Switch />
Enable notifications
</Label>Using Cubitt's URL-state hooks, you can sync the switch state with the URL by providing a paramName:
// Boolean state synced with ?notifications=true
<Switch paramName="notifications" defaultChecked={false} />
// With label and URL state:
<Label orientation="horizontal">
<Switch paramName="darkMode" defaultChecked={false} />
Enable dark mode
</Label>
// Advanced options:
<Switch
paramName="setting"
paramClearOnDefault={true} // Remove param when value equals default
paramDebounce={150} // Debounce URL updates
onUrlValueChange={(checked) => console.log('Setting enabled:', checked)}
defaultChecked={false}
/>Examples
Default
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<Label orientation="horizontal">
<Switch />
Default switch
</Label>
);
}Sizes
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<div className="flex items-center gap-6">
<Label orientation="horizontal">
<Switch size="sm" />
Small
</Label>
<Label orientation="horizontal">
<Switch size="md" />
Medium
</Label>
<Label orientation="horizontal">
<Switch size="lg" />
Large
</Label>
</div>
);
}Checked by Default
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<Label orientation="horizontal">
<Switch defaultChecked />
Enabled by default
</Label>
);
}Disabled
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<div className="flex flex-col gap-4">
<Label orientation="horizontal">
<Switch disabled />
Disabled (off)
</Label>
<Label orientation="horizontal">
<Switch disabled defaultChecked />
Disabled (on)
</Label>
</div>
);
}With Description
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<Label orientation="horizontal" className="items-start gap-3">
<Switch />
<div className="grid gap-1.5">
<span className="font-medium">Marketing emails</span>
<p className="text-sm text-muted-foreground">
Receive emails about new products, features, and more.
</p>
</div>
</Label>
);
}Settings Card
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<Label
orientation="horizontal"
className="hover:bg-accent/20 items-start gap-3 rounded-xl border p-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 transition-colors"
>
<Switch id="switch-1" size="sm" />
<div className="grid gap-1.5 font-normal">
<p className="text-sm leading-none font-medium">Enable notifications</p>
<p className="text-muted-foreground text-sm">
You can enable or disable notifications at any time.
</p>
</div>
</Label>
);
}URL State
Sync a switch state with the URL. Try toggling the switch and refreshing the page or sharing the URL.
import { Switch, Label } from "@tilt-legal/cubitt-components/primitives";
export default function Component() {
return (
<Label orientation="horizontal">
<Switch paramName="demo-notifications" defaultChecked={false} />
Enable notifications
</Label>
);
}API Reference
Switch
The root component for creating switches with multiple size variants.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | The controlled checked state of the switch. |
defaultChecked | boolean | false | The default checked state when uncontrolled. |
onCheckedChange | (checked: boolean) => void | — | Callback fired when the checked state changes. |
size | "sm" | "md" | "lg" | "md" | The size of the switch. |
disabled | boolean | false | Whether the switch is disabled. |
required | boolean | false | Whether the switch is required. |
name | string | — | The name of the switch for form submission. |
value | string | "on" | The value of the switch when in a form. |
id | string | — | The HTML id for label association. |
className | string | — | Additional CSS classes for the switch. |
children | React.ReactNode | — | Custom thumb content (defaults to <code><SwitchThumb /></code>). |
URL State Props
When provided with a paramName, the switch will sync its state with URL parameters via TanStack Router search params.
| Prop | Type | Default | Description |
|---|---|---|---|
paramName | string | — | URL parameter name for syncing state with URL. Enables URL state management. |
onUrlValueChange | (checked: boolean) => void | — | Callback when URL parameter value changes. |
paramClearOnDefault | boolean | true | Remove URL param when value equals default. |
paramDebounce | number | — | Debounce URL updates in milliseconds. |
paramThrottle | number | — | Throttle URL updates in milliseconds. |
SwitchThumb
The thumb component that slides within the switch track.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | — | Override the size from parent Switch. |
className | string | — | Additional CSS classes for the thumb. |