All files / src/components/common/Button index.tsx

100% Statements 47/47
100% Branches 6/6
100% Functions 1/1
100% Lines 47/47

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 76 77 78 79      1x     1x                                       1x 1x 1x 1x 1x 1x 1x 1x   1x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x   331x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x 331x   331x 2x 2x 2x   329x 329x 329x 146x   329x   331x   331x  
import { ReactNode } from 'react';
 
// Utils
import { combineClasses } from '@shared/utils';
 
// Icons
import LoaderCircleIcon from '@shared/icons/LoaderCircleIcon';
 
// TODO: Will add more types later
type ButtonVariant = 'default' | 'suggestion';
 
interface ButtonProps {
  isActive?: boolean;
  icon?: ReactNode;
  selectedIcon?: ReactNode;
  children?: ReactNode;
  label?: string;
  onClick?: () => void;
  disabled?: boolean;
  isLoading?: boolean;
  className?: string;
  id?: string;
  type?: 'button' | 'submit';
  variant?: ButtonVariant;
}
 
const VARIANT_CLASSES: Record<ButtonVariant, string> = {
  default: '',
  suggestion: combineClasses(
    'h-8 px-3 rounded-md text-3xs font-medium transition-colors duration-200',
    'bg-primary-200 hover:bg-primary-300/60 text-primary-700',
    'dark:bg-white/10 dark:hover:bg-white/30 dark:text-white dark:border dark:border-white/30',
  ),
};
 
export const Button = ({
  isActive,
  icon,
  selectedIcon,
  onClick,
  children,
  disabled = false,
  isLoading = false,
  className,
  id,
  type = 'button',
  variant = 'default',
}: ButtonProps) => {
  const Icon = isActive ? selectedIcon : icon;
 
  return (
    <button
      type={type}
      data-testid={id}
      disabled={disabled}
      aria-pressed={isActive}
      className={combineClasses(
        'flex items-center justify-center gap-1 font-poppins text-xs leading-sm',
        VARIANT_CLASSES[variant],
        className,
      )}
      onClick={onClick}
    >
      {isLoading ? (
        <div className="flex-center">
          <LoaderCircleIcon className="size-4 w-full animate-spin" />
        </div>
      ) : (
        <>
          {children}
          {icon && (
            <span className="flex items-center justify-center">{Icon}</span>
          )}
        </>
      )}
    </button>
  );
};