toggle_on

Switch

On/off toggle for immediate settings.

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

Switch — Props
PropTypeRequiredDefaultDescription
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).
disabledbooleanNofalseDisables the native input.
requiredbooleanNofalseAdds required attribute and a required class to the root label.
isCheckedbooleanNoundefinedWhether the switch is on. Recommended to always pass a boolean when controlling state.
onChange(e: any) => voidNoundefinedForwarded to the native input. Use it to update external state (recommended).
onClick(e: any) => voidNoundefinedForwarded to the native input.
labelContentstringNoundefinedText shown next to the switch.
labelPosition"left" | "right"No"right"Label position relative to the control.
extraTextstringNoundefinedHelper text rendered under the switch.
extraTextState"support" | "success" | "error"No"support"Helper text semantic state (affects styling).
nameIconstringNo"done"Material Symbols icon name rendered inside the thumb.
displayIconbooleanNoundefinedIf 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.