// components/ui/Switch.tsx 'use client' import type { ChangeEvent } from 'react' import clsx from 'clsx' type SwitchSize = 'default' | 'short' type SwitchVariant = 'simple' | 'icon' export type SwitchProps = { checked: boolean onChange: (checked: boolean) => void id?: string name?: string disabled?: boolean required?: boolean ariaLabel?: string ariaLabelledby?: string ariaDescribedby?: string size?: SwitchSize variant?: SwitchVariant compact?: boolean className?: string } export default function Switch({ checked, onChange, id, name, disabled, required, ariaLabel, ariaLabelledby, ariaDescribedby, size = 'default', variant = 'simple', compact = false, className, }: SwitchProps) { const handleChange = (e: ChangeEvent) => { if (disabled) return onChange(e.target.checked) } const baseInput = clsx( 'absolute inset-0 size-full appearance-none focus:outline-hidden', disabled && 'cursor-not-allowed' ) const rootBase = 'group relative inline-flex shrink-0 rounded-full bg-gray-200 p-0.5 inset-ring inset-ring-gray-900/5 outline-offset-2 outline-indigo-600 transition-colors duration-200 ease-in-out has-checked:bg-indigo-600 has-focus-visible:outline-2 dark:bg-white/5 dark:inset-ring-white/10 dark:outline-indigo-500 dark:has-checked:bg-indigo-500' if (size === 'short') { const trackClass = compact ? 'h-4 w-8' : 'h-5 w-10' const thumbClass = compact ? 'size-3 rounded-full bg-white shadow-xs ring-1 ring-gray-900/5 transition-transform duration-200 ease-in-out group-has-checked:translate-x-4' : 'size-4 rounded-full bg-white shadow-xs ring-1 ring-gray-900/5 transition-transform duration-200 ease-in-out group-has-checked:translate-x-5' return (
) } const trackClass = compact ? 'h-5 w-9' : 'h-6 w-11' const thumbClass = compact ? 'size-4 rounded-full bg-white shadow-xs ring-1 ring-gray-900/5 transition-transform duration-200 ease-in-out group-has-checked:translate-x-4' : 'size-5 rounded-full bg-white shadow-xs ring-1 ring-gray-900/5 transition-transform duration-200 ease-in-out group-has-checked:translate-x-5' const iconSizeClass = compact ? 'size-2.5' : 'size-3' return (
{variant === 'icon' ? ( ) : ( )}
) }