All files Switch.tsx

100% Statements 39/39
100% Branches 9/9
100% Functions 2/2
100% Lines 39/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 572x 2x                 2x 11x 11x 11x 11x 11x 11x 11x   11x 2x 2x 2x 2x 2x   11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 3x 8x 11x 11x   11x   11x 11x 11x 11x 3x 8x         11x   1x  
import React, { useState } from 'react';
import { cn } from '../lib/utils';
 
interface SwitchProps
  extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange'> {
  checked?: boolean;
  onChange?: (checked: boolean) => void;
  disabled?: boolean;
}
 
const Switch: React.FC<SwitchProps> = ({
  className,
  checked: controlledChecked,
  onChange,
  disabled,
  ...props
}) => {
  const [isChecked, setIsChecked] = useState(controlledChecked ?? false);
 
  const handleClick = () => {
    if (disabled) return;
    const newChecked = !isChecked;
    setIsChecked(newChecked);
    onChange?.(newChecked);
  };
 
  return (
    <button
      type='button'
      role='switch'
      aria-checked={isChecked}
      disabled={disabled}
      onClick={handleClick}
      className={cn(
        'inline-flex h-[1.15rem] w-8 items-center rounded-full transition-all focus-visible:ring-[3px] focus-visible:ring-ring/50',
        isChecked
          ? 'bg-primary dark:bg-primary-foreground'
          : 'bg-input dark:bg-input/80',
        disabled && 'cursor-not-allowed opacity-50',
        className
      )}
      {...props}
    >
      <span
        className={cn(
          'block h-4 w-4 rounded-full bg-background shadow transition-transform',
          isChecked
            ? 'translate-x-[calc(100%-2px)] dark:bg-primary-foreground'
            : 'translate-x-0 dark:bg-foreground'
        )}
      />
    </button>
  );
};
 
export { Switch };