Switch
An accessible on/off toggle (Base UI: role="switch" with a hidden real input, so it submits in a form and pairs with Field).
Colors
Sizes
Real use · notification settings
Using Switch
Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.
Plain HTML — CSS classes
The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path ships no JavaScript, so Switch is styled but inert: its behavior comes from switch. For that behavior with no framework, use the node-tree path below.
/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";Root class switch, with 14 modifiers:
.switch.switch-accent.switch-error.switch-info.switch-lg.switch-md.switch-neutral.switch-primary.switch-secondary.switch-sm.switch-success.switch-thumb.switch-warning.switch-xl.switch-xs
React
Typed components over those same classes, with behavior and accessibility from Base UI.
npm i @wizeworks/silicaui-reactimport { Switch } from "@wizeworks/silicaui-react";Props
| Prop | Type | Required | Description |
|---|---|---|---|
| color | SilicaColor | no | Accent for the checked track. |
| size | SilicaSize | no | Track height (width follows at 1.75×). |
Source of the demo above
The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.
Show source
import { useState } from "react";
import { Switch } from "@wizeworks/silicaui-react";
import { Section, Row } from "../lib/Section";
import { SIZES } from "../lib/data";
const SETTINGS = [
{ key: "push", label: "Push notifications", defaultOn: true },
{ key: "email", label: "Email digest", defaultOn: true },
{ key: "sms", label: "SMS alerts", defaultOn: false },
];
export function SwitchDemo() {
const [on, setOn] = useState<Record<string, boolean>>({
push: true,
email: true,
sms: false,
});
return (
<>
<Section title="Colors">
<Row>
<Switch defaultChecked />
<Switch color="primary" defaultChecked />
<Switch color="success" defaultChecked />
<Switch color="warning" defaultChecked />
<Switch color="error" defaultChecked />
<Switch color="brand" defaultChecked />
<Switch disabled />
</Row>
</Section>
<Section title="Sizes">
<Row>
{SIZES.filter((s) => s !== "xl").map((size) => (
<Switch key={size} color="primary" size={size} defaultChecked />
))}
</Row>
</Section>
<Section title="Real use · notification settings">
<div className="flex max-w-sm flex-col gap-3 rounded-box border border-base-300 bg-base-100 p-4">
{SETTINGS.map((s) => (
<label key={s.key} className="flex items-center justify-between gap-4 text-sm">
{s.label}
<Switch
color="primary"
checked={on[s.key]}
onCheckedChange={(v) => setOn((p) => ({ ...p, [s.key]: v }))}
/>
</label>
))}
</div>
</Section>
</>
);
}Vanilla — node tree to HTML
switch — a role=switch element the CSS keys off [data-checked] for (Base UI's synthetic attribute, ported verbatim — a bare <input type=checkbox> would NOT match .switch's selectors). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.
npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviorsimport { atom, toHtml } from "@wizeworks/silicaui-html";
const node = atom("Switch", "switch", { /* props */ });
const markup = toHtml(node);Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "switch switch-primary" rather than passing a colour as a prop.
- Takes children
- no
- Hydrated by
switch
Load @wizeworks/silicaui-behaviors on the page or this markup renders correctly and does nothing.
The full API for Switch, on every path, is available through the Silica MCP server.