Skip to content
VEXA
Forms

Switch

Client leaf

An instant on/off toggle for a single setting.

Live preview

Rendered from the installed VEXA source — the same files you receive.

Installation

Adds the component source to your project. Registry dependencies are pulled in automatically.

npx shadcn@latest add https://vexa.valfiguer.com/r/switch.json

Installs to components/vexa/switch.tsx

npm dependencies

  • @radix-ui/react-switch

Registry dependencies

  • @vexa/utils

Other VEXA items this component needs. Install them first — they are resolved automatically by the CLI.

Source

Copy this into its target path, or install it with the command above.

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

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

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

/**
 * Switch — an instant on/off toggle for a single setting.
 *
 * Client leaf. Radix supplies `role="switch"`, `aria-checked`, and the keyboard
 * model (Space/Enter toggles). Use a Switch for settings that apply immediately;
 * prefer a Checkbox inside forms that are submitted. State is conveyed by the
 * thumb position, not color alone. Provide an accessible name via `<Label>` or
 * `aria-label`. The thumb transition respects reduced-motion.
 */
export 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 cursor-pointer items-center rounded-full border border-transparent",
        "transition-colors duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]",
        "outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background",
        "disabled:cursor-not-allowed disabled:opacity-50",
        "data-[state=unchecked]:bg-vexa-input data-[state=checked]:bg-vexa-primary",
        className,
      )}
      {...props}
    >
      <SwitchPrimitive.Thumb
        data-slot="switch-thumb"
        className={cn(
          "pointer-events-none block size-5 rounded-full bg-vexa-surface-raised shadow-vexa-sm ring-0",
          "transition-transform duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)] motion-reduce:transition-none",
          "translate-x-0.5 data-[state=checked]:translate-x-[1.375rem]",
        )}
      />
    </SwitchPrimitive.Root>
  );
}

Details

Example

tsx
<div className="flex items-center gap-2"><Switch id="wifi" /><Label htmlFor="wifi">Wi-Fi</Label></div>

Accessibility

role=switch with aria-checked; Space/Enter toggles. State is shown by the thumb position, not color alone. The thumb transition respects reduced motion.