Component

Switch

Toggle for a setting that takes effect immediately.

Text referenceSource and examples as JSON

npx -y github:anwarlemu/opencommerce-brand-cli#release add switch --surface site

Run from the target React 19.2+ app root with Tailwind CSS 4 and the @/* source alias.

switch.preview
Preview

Usage

use-it-for.md

Pair with Label. Connect checked and onCheckedChange when the application owns the setting.

never.md
  • Pill-shaped switches
  • Colors other than blue for on
  • A switch inside a form that needs a submit (use a checkbox)

Exports: Switch. This component includes a client boundary. Keep event handlers and state in a client component.

Dependencies: @radix-ui/react-switch.

Example

examples/switch.tsx
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";

export function Site() {
  return (
    <div className="grid max-w-sm gap-4">
      <div className="flex items-center justify-between gap-4">
        <Label variant="control" htmlFor="switch-receipts">Email a receipt for every purchase</Label>
        <Switch id="switch-receipts" defaultChecked />
      </div>
      <div className="flex items-center justify-between gap-4">
        <Label variant="control" htmlFor="switch-pause">Pause this card</Label>
        <Switch id="switch-pause" />
      </div>
      <div className="flex items-center justify-between gap-4">
        <Label variant="control" htmlFor="switch-locked">International purchases</Label>
        <Switch id="switch-locked" disabled />
      </div>
    </div>
  );
}

Source

components/ui/switch.tsx
"use client";

import * as React from "react";
import * as SwitchPrimitive from "@radix-ui/react-switch";

import { cn } from "@/lib/utils";

// A track and key, flat as the brand's keys: off, a mist track on the 16 percent ink edge with a white key at the left;
// on, the track turns blue and the key slides right (200ms ease-out, on transform). The key sits 2px inside the track,
// its corners concentric with the track's 8px. Reduced motion moves it at once.
function Switch({ className, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root>) {
  return (
    <SwitchPrimitive.Root
      data-slot="switch"
      className={cn(
        "peer inline-flex h-6 w-11 shrink-0 items-center rounded-control border outline-none transition-[background-color,border-color] duration-200 ease-out focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-line-brand-edge data-[state=checked]:bg-primary data-[state=unchecked]:border-hairline data-[state=unchecked]:bg-subtle motion-reduce:transition-none",
        className,
      )}
      {...props}
    >
      <SwitchPrimitive.Thumb
        data-slot="switch-thumb"
        className="pointer-events-none block size-4.5 translate-x-0.5 rounded-sm border border-hairline bg-white shadow-tile transition-[translate] duration-200 ease-out data-[state=checked]:translate-x-5.5 motion-reduce:transition-none"
      />
    </SwitchPrimitive.Root>
  );
}

export { Switch };

Reference: Extension from opencommerce-agentcard-web src/app/globals.css (.btn-primary, .feat-tile).