All files / src/components/Chatbot Button.tsx

100% Statements 73/73
100% Branches 8/8
100% Functions 0/0
100% Lines 73/73

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 80 81 82 83 84 85 86 87 88 89 90 91 92 93  1x 1x 1x     1x     1x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x   8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x   8x 2x 2x 2x   6x   8x   8x 1x 1x  
// Libs
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';
import { ButtonHTMLAttributes, forwardRef } from 'react';
 
// Utils
import { combineClasses } from '@shared/utils';
 
// Icons
import { LoaderCircleIcon } from '../icons/reacts';
 
export const buttonVariants = cva(
  'flex-center gap-2 h-10 px-[18px] whitespace-nowrap rounded-md text-3xs font-semibold transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
  {
    variants: {
      variant: {
        default:
          'bg-secondary text-secondary-foreground hover:bg-secondary-100',
        outline: 'border border-secondary text-secondary hover:bg-secondary/10',
        disabled: 'bg-muted-foreground/20 text-slate-800',
        ghost:
          'border border-slate-200 text-foreground hover:bg-slate-500/10 dark:bg-slate-700 dark:hover:bg-slate-200/40',
        text: 'flex-start text-slate-700 dark:text-foreground gap-2 hover:text-black text-4xs outline-none bg-transparent p-0',
        uppercase:
          'uppercase bg-secondary text-secondary-foreground hover:bg-secondary-100 rounded-sm',
        primary:
          'bg-primary-700 rounded-3xl text-primary-foreground h-8 text-4xs font-medium hover:bg-primary-600',
      },
      size: {
        default: 'py-3.5 min-w-32',
        full: 'w-full',
        sm: 'min-w-[107px]',
        lg: 'min-w-[280px]',
        fit: 'w-fit h-fit',
        icon: 'h-5 w-5',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  },
);
 
export interface ButtonProps
  extends ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
  isLoading?: boolean;
}
 
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      className,
      variant = 'default',
      isLoading = false,
      size,
      asChild = false,
      children,
      disabled,
      ...props
    },
    ref,
  ) => {
    const Comp = asChild ? Slot : 'button';
 
    return (
      <Comp
        className={combineClasses(
          buttonVariants({
            variant: disabled ? 'disabled' : variant,
            size,
            className,
          }),
        )}
        ref={ref}
        disabled={disabled || isLoading}
        {...props}
      >
        {isLoading ? (
          <div className="flex-center">
            <LoaderCircleIcon className="size-4 w-full animate-spin" />
          </div>
        ) : (
          children
        )}
      </Comp>
    );
  },
);
Button.displayName = 'Button';