Skip to content
Dethink Components

ComponentsSwitch

Switch

Turn a setting on or off.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
import { Switch } from "@dethink/components";

Try the examples, then open the code to use them in your app.

With Field anatomy

Field wiring gives the switch its label and an optional description.

Anonymous metrics that help prioritize fixes.

Show sourceexamples/switch/basic.tsx
examples/switch/basic.tsx
"use client";

import {
  Field,
  FieldContent,
  FieldControl,
  FieldDescription,
  FieldLabel,
  Switch,
} from "@dethink/components";

export function SwitchBasic() {
  return (
    <div className="mx-auto max-w-sm space-y-4">
      <Field id="sw-autosave" orientation="horizontal">
        <FieldControl asChild>
          <Switch name="autosave" defaultChecked />
        </FieldControl>
        <FieldLabel>Autosave</FieldLabel>
      </Field>
      <Field id="sw-usage" orientation="horizontal">
        <FieldControl asChild>
          <Switch name="usage" />
        </FieldControl>
        <FieldContent>
          <FieldLabel>Share usage data</FieldLabel>
          <FieldDescription>
            Anonymous metrics that help prioritize fixes.
          </FieldDescription>
        </FieldContent>
      </Field>
    </div>
  );
}

States and sizes

On, off, disabled, invalid, and the three control sizes.

Show sourceexamples/switch/states.tsx
examples/switch/states.tsx
"use client";

import { Field, FieldControl, FieldLabel, Switch } from "@dethink/components";

export function SwitchStates() {
  return (
    <div className="mx-auto grid max-w-md gap-4 sm:grid-cols-2">
      <Field id="sw-on" orientation="horizontal">
        <FieldControl asChild>
          <Switch defaultChecked />
        </FieldControl>
        <FieldLabel>On</FieldLabel>
      </Field>
      <Field id="sw-off" orientation="horizontal">
        <FieldControl asChild>
          <Switch />
        </FieldControl>
        <FieldLabel>Off</FieldLabel>
      </Field>
      <Field id="sw-disabled" orientation="horizontal">
        <FieldControl asChild>
          <Switch disabled defaultChecked />
        </FieldControl>
        <FieldLabel>Disabled</FieldLabel>
      </Field>
      <Field id="sw-invalid" orientation="horizontal">
        <FieldControl asChild>
          <Switch invalid />
        </FieldControl>
        <FieldLabel>Invalid</FieldLabel>
      </Field>
      <Field id="sw-sm" orientation="horizontal">
        <FieldControl asChild>
          <Switch controlSize="sm" defaultChecked />
        </FieldControl>
        <FieldLabel>Small</FieldLabel>
      </Field>
      <Field id="sw-lg" orientation="horizontal">
        <FieldControl asChild>
          <Switch controlSize="lg" defaultChecked />
        </FieldControl>
        <FieldLabel>Large</FieldLabel>
      </Field>
    </div>
  );
}

Optional spring motion

Add spring for a softly bouncing thumb. Standard motion remains the default; reduced-motion preferences are respected automatically.

Show sourceexamples/switch/spring.tsx
examples/switch/spring.tsx
"use client";

import { Switch } from "@dethink/components";

export function SwitchSpring() {
  return (
    <div className="grid w-full max-w-md gap-6 sm:grid-cols-2">
      <label
        htmlFor="switch-spring-standard"
        className="flex items-center gap-3 text-sm"
      >
        <Switch id="switch-spring-standard" />
        Standard motion
      </label>
      <label
        htmlFor="switch-spring-motion"
        className="flex items-center gap-3 text-sm"
      >
        <Switch id="switch-spring-motion" spring />
        Spring motion
      </label>
      <label
        htmlFor="switch-spring-small"
        className="flex items-center gap-3 text-sm"
      >
        <Switch
          id="switch-spring-small"
          spring
          controlSize="sm"
          defaultChecked
        />
        Small spring
      </label>
      <label
        htmlFor="switch-spring-large"
        className="flex items-center gap-3 text-sm"
      >
        <Switch
          id="switch-spring-large"
          spring
          controlSize="lg"
          defaultChecked
        />
        Large spring
      </label>
      <label
        htmlFor="switch-spring-disabled"
        className="flex items-center gap-3 text-sm"
      >
        <Switch id="switch-spring-disabled" spring disabled defaultChecked />
        Disabled spring
      </label>
      <label
        htmlFor="switch-spring-rtl"
        className="flex items-center gap-3 text-sm"
        dir="rtl"
      >
        <Switch id="switch-spring-rtl" spring />
        RTL spring
      </label>
    </div>
  );
}

Examples that combine components for common tasks.

Settings panel with dependent toggles

Child switches only apply while the master switch is on, so they disable โ€” and visually recede โ€” instead of silently doing nothing. Disabled state is real, so assistive tech announces it.

Master switch for all channels.

Show sourceexamples/switch/recipe-settings.tsx
examples/switch/recipe-settings.tsx
"use client";

import { useState } from "react";
import {
  Field,
  FieldContent,
  FieldControl,
  FieldDescription,
  FieldLabel,
  Switch,
} from "@dethink/components";

/**
 * Dependent toggles: children only apply while the parent is on, so they
 * disable (and visually recede) rather than silently doing nothing.
 */
export function SwitchRecipeSettings() {
  const [notifications, setNotifications] = useState(true);
  const [mentions, setMentions] = useState(true);
  const [digest, setDigest] = useState(false);

  return (
    <div className="mx-auto max-w-sm space-y-4">
      <Field id="ns-all" orientation="horizontal">
        <FieldControl asChild>
          <Switch checked={notifications} onCheckedChange={setNotifications} />
        </FieldControl>
        <FieldContent>
          <FieldLabel className="font-medium">Notifications</FieldLabel>
          <FieldDescription>Master switch for all channels.</FieldDescription>
        </FieldContent>
      </Field>
      <div
        className={`border-border space-y-4 border-l pl-6 transition-opacity ${
          notifications ? "" : "opacity-50"
        }`}
      >
        <Field id="ns-mentions" orientation="horizontal">
          <FieldControl asChild>
            <Switch
              checked={mentions}
              onCheckedChange={setMentions}
              disabled={!notifications}
            />
          </FieldControl>
          <FieldLabel>Mentions and replies</FieldLabel>
        </Field>
        <Field id="ns-digest" orientation="horizontal">
          <FieldControl asChild>
            <Switch
              checked={digest}
              onCheckedChange={setDigest}
              disabled={!notifications}
            />
          </FieldControl>
          <FieldLabel>Daily digest email</FieldLabel>
        </Field>
      </div>
    </div>
  );
}

Switch renders a real input element, so native form behavior applies.

Switch props
PropWhat it doesDefault
springbooleanOpt in to a lazily loaded Motion spring for the thumb. Respects reduced motion.false
checked / defaultCheckedbooleanControlled or uncontrolled on/off state.false
onCheckedChange(checked: boolean) => voidCalled with the new state when the user toggles the control.Not set
controlSize"sm" | "md" | "lg"Track and thumb dimensions."md"
invalidbooleanShows an error style and marks the field as invalid for screen readers.false
โ€ฆnative input propsInputHTMLAttributesRenders a real checkbox input with a switch role: name, value, disabled, and form behavior are native.Not set