import { forwardRef, InputHTMLAttributes, ReactNode } from 'react' import clsx from 'clsx' export interface CheckboxProps extends Omit, 'type'> { label?: string | ReactNode description?: string error?: string } const Checkbox = forwardRef( ({ className, label, description, error, id, ...props }, ref) => { const checkboxId = id || (typeof label === 'string' ? label.toLowerCase().replace(/\s+/g, '-') : undefined) return ( {(label || description) && ( {label && ( {label} )} {description && ( {description} )} {error && {error}} )} ) } ) Checkbox.displayName = 'Checkbox' export default Checkbox // Switch component export interface SwitchProps { checked: boolean onChange: (checked: boolean) => void label?: string description?: string disabled?: boolean size?: 'sm' | 'md' | 'lg' } export function Switch({ checked, onChange, label, description, disabled = false, size = 'md', }: SwitchProps) { const sizeStyles = { sm: { track: 'w-8 h-4', thumb: 'w-3 h-3', translate: 'translate-x-4', }, md: { track: 'w-11 h-6', thumb: 'w-5 h-5', translate: 'translate-x-5', }, lg: { track: 'w-14 h-7', thumb: 'w-6 h-6', translate: 'translate-x-7', }, } return ( {(label || description) && ( {label && ( {label} )} {description && ( {description} )} )} !disabled && onChange(!checked)} className={clsx( 'relative inline-flex flex-shrink-0 rounded-full cursor-pointer', 'transition-colors duration-200 ease-in-out', 'focus:outline-none focus:ring-2 focus:ring-accent-500 focus:ring-offset-2 focus:ring-offset-background-900', sizeStyles[size].track, checked ? 'bg-accent-500' : 'bg-slate-600', disabled && 'opacity-50 cursor-not-allowed' )} disabled={disabled} > ) } // Radio button component export interface RadioProps extends Omit, 'type'> { label?: string } export const Radio = forwardRef( ({ className, label, id, ...props }, ref) => { const radioId = id || label?.toLowerCase().replace(/\s+/g, '-') return ( {label && ( {label} )} ) } ) Radio.displayName = 'Radio'
{description}
{error}