Switch
Switch Examples
Toggle control built on a native input[type=checkbox] with role="switch". Recommended usage is controlled via isChecked + onChange.
Basic controlled usage
Keep UI in sync by passing isChecked + onChange.
Live preview
Controlled switch
import { useState } from "react";
import Switch from "@/packages/ui/src/_components/forms/switch/Switch";
export default function Example() {
const [checked, setChecked] = useState(false);
return (
<Switch
labelContent="Enable notifications"
isChecked={checked}
onChange={(e: any) => setChecked(e.target.checked)}
/>
);
}Label position
Move the label to the left or keep it on the right (default).
Live preview
Left vs right
import { useState } from "react";
import Switch from "@/packages/ui/src/_components/forms/switch/Switch";
export default function Example() {
const [dark, setDark] = useState(true);
return (
<Switch
labelContent="Dark mode"
labelPosition="left"
isChecked={dark}
onChange={() => setDark((v) => !v)}
/>
);
}Variants
Use variant for semantic tone (primary/success/danger/etc.).
Live preview
All variants
import Switch from "@/_components/forms/switch/Switch";
export default function Example() {
return (
<>
<Switch labelContent="Primary" variant="primary" isChecked onChange={() => {}} />
<Switch labelContent="Secondary" variant="secondary" isChecked onChange={() => {}} />
<Switch labelContent="Tertiary" variant="tertiary" isChecked onChange={() => {}} />
<Switch labelContent="Success" variant="success" isChecked onChange={() => {}} />
<Switch labelContent="Warning" variant="warning" isChecked onChange={() => {}} />
<Switch labelContent="Danger" variant="danger" isChecked onChange={() => {}} />
<Switch labelContent="Info" variant="info" isChecked onChange={() => {}} />
</>
);
}Sizes
Use size to match the density of your UI (small/medium/large).
Live preview
Small / medium / large
import { useState } from "react";
import Switch from "@/_components/forms/switch/Switch";
export default function Example() {
const [checked, setChecked] = useState(true);
return (
<>
<Switch labelContent="Small" size="small" isChecked={checked} onChange={() => setChecked((v) => !v)} />
<Switch labelContent="Medium" size="medium" isChecked={checked} onChange={() => setChecked((v) => !v)} />
<Switch labelContent="Large" size="large" isChecked={checked} onChange={() => setChecked((v) => !v)} />
</>
);
}Helper text and semantic state
Use extraText + extraTextState to communicate support/success/error.
• If the implementation always renders the helper <p>, prefer passing an empty string to avoid blank space when you do not need helper text.
Live preview
May use additional data.
Everything looks good.
You must enable this option to continue.
Helper text
import { useState } from "react";
import Switch from "@/_components/forms/switch/Switch";
export default function Example() {
const [sync, setSync] = useState(true);
return (
<>
<Switch
labelContent="Sync over cellular"
isChecked={sync}
onChange={() => setSync((v) => !v)}
extraText="May use additional data."
extraTextState="support"
/>
<Switch
labelContent="Account verified"
isChecked
onChange={() => {}}
extraText="Everything looks good."
extraTextState="success"
/>
<Switch
labelContent="Permissions"
isChecked={false}
onChange={() => {}}
extraText="You must enable this option to continue."
extraTextState="error"
/>
</>
);
}Thumb icon
Use nameIcon to change the Material Symbols icon displayed in the thumb.
• If displayIcon exists in the type but has no effect, you can omit it.
Live preview
Custom icons
import { useState } from "react";
import Switch from "@/_components/forms/switch/Switch";
export default function Example() {
const [notifications, setNotifications] = useState(true);
return (
<>
<Switch labelContent="Menu" nameIcon="menu" isChecked onChange={() => {}} />
<Switch
labelContent="Notifications"
nameIcon="notifications"
isChecked={notifications}
onChange={() => setNotifications((v) => !v)}
/>
<Switch labelContent="Location" nameIcon="location_on" disabled isChecked onChange={() => {}} />
</>
);
}Disabled and required
Native flags forwarded to the input.
Live preview
Disabled + required
import Switch from "@/_components/forms/switch/Switch";
export default function Example() {
return (
<>
<Switch labelContent="Mobile data" disabled isChecked onChange={() => {}} />
<Switch labelContent="Accept terms" required isChecked={false} onChange={() => {}} />
</>
);
}Settings panel (realistic composition)
Multiple switches with shared controls and helper text.
Live preview
Recommended to keep enabled.
Visible to nearby devices.
No alerts will be shown.
This may expose experimental settings.
Settings panel
import { useState } from "react";
import Switch from "@/_components/forms/switch/Switch";
import { Button } from "@/_components/buttons_variants/buttons/Button";
export default function Example() {
const [bluetooth, setBluetooth] = useState(true);
const [wifi, setWifi] = useState(true);
const [notifications, setNotifications] = useState(false);
const [advanced, setAdvanced] = useState(false);
return (
<>
<div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
<Button
variant="secondary"
onClick={() => {
setBluetooth(true);
setWifi(true);
setNotifications(true);
setAdvanced(true);
}}
>
Enable all
</Button>
<Button
variant="transparent"
onClick={() => {
setBluetooth(false);
setWifi(false);
setNotifications(false);
setAdvanced(false);
}}
>
Disable all
</Button>
</div>
<Switch
labelContent="Wi‑Fi"
variant="primary"
isChecked={wifi}
onChange={() => setWifi((v) => !v)}
extraText="Recommended to keep enabled."
extraTextState="support"
/>
<Switch
labelContent="Bluetooth"
variant="secondary"
isChecked={bluetooth}
onChange={() => setBluetooth((v) => !v)}
extraText={bluetooth ? "Visible to nearby devices." : "Hidden."}
extraTextState={bluetooth ? "support" : "error"}
/>
<Switch
labelContent="Notifications"
nameIcon="notifications"
variant="info"
isChecked={notifications}
onChange={() => setNotifications((v) => !v)}
extraText={notifications ? "Alerts enabled." : "No alerts will be shown."}
extraTextState={notifications ? "success" : "error"}
/>
<Switch
labelContent="Advanced mode"
labelPosition="left"
size="large"
variant="warning"
nameIcon="settings"
isChecked={advanced}
onChange={() => setAdvanced((v) => !v)}
extraText="This may expose experimental settings."
extraTextState="support"
/>
</>
);
}On this page
Switch Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| variant | "primary" | "secondary" | "tertiary" | "success" | "warning" | "danger" | "info" | No | "primary" | Visual/semantic style (cssnt-switch--*). |
| size | "small" | "medium" | "large" | No | "small" | Size modifier (cssnt-switch--sm/md/lg). |
| disabled | boolean | No | false | Disables the native input. |
| required | boolean | No | false | Adds required attribute and a required class to the root label. |
| isChecked | boolean | No | undefined | Whether the switch is on. Recommended to always pass a boolean when controlling state. |
| onChange | (e: any) => void | No | undefined | Forwarded to the native input. Use it to update external state (recommended). |
| onClick | (e: any) => void | No | undefined | Forwarded to the native input. |
| labelContent | string | No | undefined | Text shown next to the switch. |
| labelPosition | "left" | "right" | No | "right" | Label position relative to the control. |
| extraText | string | No | undefined | Helper text rendered under the switch. |
| extraTextState | "support" | "success" | "error" | No | "support" | Helper text semantic state (affects styling). |
| nameIcon | string | No | "done" | Material Symbols icon name rendered inside the thumb. |
| displayIcon | boolean | No | undefined | If present in the props type: intended to toggle the thumb icon. If the current implementation always renders the icon, this prop will have no effect. |
Components