Skip to content
EMBOSS
Docs menu

Switch

A console slide switch: the thumb travels a milled channel and seats with a sprung settle, with engraved I/O glyphs for state.

@emboss/switch

Installation

pnpm dlx shadcn@latest add @emboss/switch

Usage

example.tsx
import { Switch } from "@/components/ui/switch";

export function Example() {
  return <Switch aria-label="Power" defaultChecked />;
}

Examples

With label

Wire a visible label with htmlFor and id.

Show code
labelled.tsx
import { Switch } from "@/components/ui/switch";

export default function SwitchLabelled() {
  return (
    <div className="flex items-center gap-3">
      <Switch id="phantom-power" />
      <label htmlFor="phantom-power" className="text-sm font-medium">
        Phantom power
      </label>
    </div>
  );
}

Disabled

Show code
disabled.tsx
import { Switch } from "@/components/ui/switch";

export default function SwitchDisabled() {
  return (
    <div className="flex items-center gap-4">
      <Switch aria-label="Locked off" disabled />
      <Switch aria-label="Locked on" disabled defaultChecked />
    </div>
  );
}

API reference

Switch

PropTypeDefaultDescription
checked / defaultChecked / onCheckedChangeboolean / boolean / (checked) => voidControlled and uncontrolled usage.
name / valuestring / stringForm participation through a hidden input when used inside a form.
disabledbooleanfalseDisables interaction and dims the control.
Data attributeDescription
data-checked / data-uncheckedReflects the current state for styling.

Keyboard

KeysAction
SpaceToggles the switch.
EnterToggles the switch.

Source

View source — switch.tsx
switch.tsx
"use client";

import { Switch as BaseSwitch } from "@base-ui/react/switch";
import { cn } from "@/lib/utils";

export type SwitchProps = React.ComponentProps<typeof BaseSwitch.Root>;

/**
 * A console slide switch. The thumb travels a milled channel and seats with
 * a sprung settle; engraved I/O glyphs keep the state readable beyond color
 * and position alone.
 *
 * @example
 * <Switch defaultChecked aria-label="Power" />
 */
function Switch({ className, ...props }: SwitchProps) {
  return (
    <BaseSwitch.Root
      data-slot="switch"
      className={cn(
        "group relative inline-flex h-6 w-10 shrink-0 cursor-pointer items-center rounded-full bg-well-deep shadow-deboss-2 focus-ring transition-colors duration-(--duration-settle) data-checked:bg-accent data-disabled:pointer-events-none data-disabled:opacity-50",
        className,
      )}
      {...props}
    >
      <span
        aria-hidden
        className="absolute left-2 font-mono text-[0.5rem] leading-none font-bold text-accent-fg opacity-0 transition-opacity duration-(--duration-settle) group-data-checked:opacity-100"
      >
        I
      </span>
      <span
        aria-hidden
        className="absolute right-1.5 font-mono text-[0.5rem] leading-none font-bold text-ink-faint transition-opacity duration-(--duration-settle) group-data-checked:opacity-0"
      >
        O
      </span>
      <BaseSwitch.Thumb
        data-slot="switch-thumb"
        className="pointer-events-none ms-0.5 size-5 rounded-full bg-surface-3 shadow-emboss-2 transition-[translate] duration-(--duration-settle) ease-(--ease-settle) data-checked:translate-x-4"
      />
    </BaseSwitch.Root>
  );
}

export { Switch };