● Zion Boggan
repos/Drophawk/frontend/components/ui/button.tsx
zionboggan.com ↗
73 lines · tsx
History for this file →
1
"use client";
2
 
3
import * as React from "react";
4
import { Slot } from "@radix-ui/react-slot";
5
import { cva, type VariantProps } from "class-variance-authority";
6
import { Loader2 } from "lucide-react";
7
import { cn } from "@/lib/utils";
8
 
9
const buttonVariants = cva(
10
  cn(
11
    "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--radius)] text-sm font-medium",
12
    "transition-[background,box-shadow,transform,color] duration-[var(--duration-fast)] cursor-pointer select-none",
13
    "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-accent-teal)]",
14
    "disabled:pointer-events-none disabled:opacity-50 active:scale-[0.98]",
15
  ),
16
  {
17
    variants: {
18
      variant: {
19
        primary:
20
          "bg-[var(--color-accent-teal)] text-[var(--color-bg-inset)] hover:bg-[var(--color-accent-teal-hover)] hover:shadow-[var(--shadow-glow-teal)]",
21
        secondary:
22
          "bg-[var(--color-bg-elevated)] text-[var(--color-fg-primary)] border border-[var(--color-border-default)] hover:border-[var(--color-border-strong)] hover:bg-[var(--color-bg-overlay)]",
23
        ghost:
24
          "text-[var(--color-fg-secondary)] hover:bg-[var(--color-bg-elevated)] hover:text-[var(--color-fg-primary)]",
25
        danger:
26
          "bg-transparent text-[var(--color-accent-red)] border border-[color-mix(in_oklch,var(--color-accent-red)_40%,transparent)] hover:bg-[color-mix(in_oklch,var(--color-accent-red)_14%,transparent)]",
27
        outline:
28
          "border border-[var(--color-border-default)] text-[var(--color-fg-primary)] hover:border-[var(--color-accent-teal)] hover:text-[var(--color-accent-teal)]",
29
      },
30
      size: {
31
        sm: "h-8 px-3 text-xs",
32
        md: "h-10 px-4",
33
        lg: "h-11 px-5 text-base",
34
        icon: "h-9 w-9",
35
      },
36
    },
37
    defaultVariants: { variant: "primary", size: "md" },
38
  },
39
);
40
 
41
export interface ButtonProps
42
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
43
    VariantProps<typeof buttonVariants> {
44
  asChild?: boolean;
45
  loading?: boolean;
46
}
47
 
48
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(function Button(
49
  { className, variant, size, asChild, loading, disabled, children, ...props },
50
  ref,
51
) {
52
  const Comp = asChild ? Slot : "button";
53
  return (
54
    <Comp
55
      ref={ref}
56
      className={cn(buttonVariants({ variant, size }), className)}
57
      disabled={disabled ?? loading}
58
      aria-busy={loading || undefined}
59
      {...props}
60
    >
61
      {asChild ? (
62
        children
63
      ) : (
64
        <>
65
          {loading ? <Loader2 className="h-4 w-4 animate-spin" aria-hidden /> : null}
66
          {children}
67
        </>
68
      )}
69
    </Comp>
70
  );
71
});
72
 
73
export { buttonVariants };