Switch
A toggle switch control for binary settings.
Demo
Dependencies
clsxtailwind-merge
Props
This is a base primitive. It accepts standard HTML attributes plus className for styling via cn().
Source
"use client";
import { useState, useCallback } from "react";
import { cn } from "@/lib/utils";
export interface SwitchProps {
checked?: boolean;
defaultChecked?: boolean;
onCheckedChange?: (checked: boolean) => void;
disabled?: boolean;
className?: string;
}
export function Switch({
checked: controlledChecked,
defaultChecked = false,
onCheckedChange,
disabled,
className,
}: SwitchProps) {
const [internalChecked, setInternalChecked] = useState(defaultChecked);
const isControlled = controlledChecked !== undefined;
const checked = isControlled ? controlledChecked : internalChecked;
const handleClick = useCallback(() => {
if (disabled) return;
const next = !checked;
if (!isControlled) setInternalChecked(next);
onCheckedChange?.(next);
}, [checked, disabled, isControlled, onCheckedChange]);
return (
<button
role="switch"
aria-checked={checked}
disabled={disabled}
onClick={handleClick}
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
checked ? "bg-gray-900" : "bg-gray-200",
className,
)}
>
<span
className={cn(
"pointer-events-none block h-4 w-4 rounded-full bg-white shadow-sm ring-0 transition-transform",
checked ? "translate-x-4" : "translate-x-0",
)}
/>
</button>
);
}
CLI
npx genui add switch