All files Toggle.tsx

100% Statements 55/55
100% Branches 10/10
100% Functions 2/2
100% Lines 55/55

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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 762x 2x 2x   2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x                           2x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x 19x   19x 19x   19x 5x 5x 4x 4x 5x 5x 5x   19x 19x 19x 19x 19x 19x 19x 19x     19x   1x  
import * as React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '../lib/utils';
 
const toggleVariants = cva(
  "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
  {
    variants: {
      variant: {
        default: 'bg-transparent',
        outline:
          'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
      },
      size: {
        default: 'h-9 px-2 min-w-9',
        sm: 'h-8 px-1.5 min-w-8',
        lg: 'h-10 px-2.5 min-w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
);
 
interface ToggleProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof toggleVariants> {
  /** Controlled pressed state */
  pressed?: boolean;
  /** Uncontrolled default pressed state */
  defaultPressed?: boolean;
  /** Handler called when pressed state changes */
  onPressedChange?: (pressed: boolean) => void;
}
 
const Toggle: React.FC<ToggleProps> = ({
  pressed,
  defaultPressed,
  onPressedChange,
  variant,
  size,
  className,
  onClick,
  ...props
}) => {
  const [internalPressed, setInternalPressed] = React.useState(
    defaultPressed ?? false
  );
  const isControlled = pressed !== undefined;
  const currentPressed = isControlled ? pressed! : internalPressed;
 
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    const newPressed = !currentPressed;
    if (!isControlled) {
      setInternalPressed(newPressed);
    }
    onPressedChange?.(newPressed);
    onClick?.(event);
  };
 
  return (
    <button
      type='button'
      data-state={currentPressed ? 'on' : 'off'}
      aria-pressed={currentPressed}
      className={cn(toggleVariants({ variant, size, className }))}
      onClick={handleClick}
      {...props}
    />
  );
};
 
export { Toggle };