55 lines · 2.0 KB
import { forwardRef } from "react";
import { cn } from "~/utils/cn";

type Variant = "primary" | "secondary" | "danger" | "ghost";
type Size = "sm" | "md";

const VARIANTS: Record<Variant, string> = {
  primary: "border-transparent bg-accent-500 text-gray-950 hover:bg-accent-400 disabled:hover:bg-accent-500",
  secondary: "border-gray-700 bg-gray-900 text-gray-200 hover:border-gray-500 hover:bg-gray-800",
  danger:
    "border-gray-700 bg-gray-900 text-danger-300 hover:border-transparent hover:bg-danger-700 hover:text-white disabled:hover:border-gray-700 disabled:hover:bg-gray-900 disabled:hover:text-danger-300",
  ghost: "border-transparent bg-transparent text-gray-400 hover:bg-gray-800/60 hover:text-gray-100",
};

const SIZES: Record<Size, string> = {
  sm: "h-7 px-2.5 text-xs",
  md: "h-9 px-3.5 text-sm",
};

export function buttonClass(variant: Variant = "secondary", size: Size = "md", className?: string): string {
  return cn(
    "inline-flex shrink-0 items-center justify-center gap-1.5 rounded-md border font-medium whitespace-nowrap transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent-500 disabled:cursor-not-allowed disabled:opacity-50",
    VARIANTS[variant],
    SIZES[size],
    className,
  );
}

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: Variant;
  size?: Size;
  pending?: boolean;
};

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
  { variant = "secondary", size = "md", pending = false, className, children, disabled, type = "button", ...rest },
  ref,
) {
  return (
    <button