File size: 2,729 Bytes
65d68f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"use client";

import { forwardRef } from "react";
import { cn } from "@/lib/utils";

// =============================================================================
// CleanButton — Black primary, gray secondary, ghost
// =============================================================================

export type CleanButtonVariant = "primary" | "secondary" | "ghost" | "outline";
export type CleanButtonSize = "sm" | "md" | "lg";

export interface CleanButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: CleanButtonVariant;
  size?: CleanButtonSize;
  fullWidth?: boolean;
  icon?: React.ReactNode;
  iconRight?: React.ReactNode;
}

const variantClasses: Record<CleanButtonVariant, string> = {
  primary:
    "bg-[#111217] text-[#fbfbfc] hover:bg-[#0b0d12] active:bg-[#1a1c24] border border-transparent shadow-[0_1px_2px_rgba(15,17,23,0.06)]",
  secondary:
    "bg-[#F0F1F4] text-[#3A3F4C] hover:bg-[#E4E6EC] active:bg-[#D4D7E0] border border-[#E4E6EC]",
  ghost:
    "bg-transparent text-[#5C6170] hover:bg-[#F3F4F7] hover:text-[#111217] active:bg-[#EBECF0] border border-transparent",
  outline:
    "bg-white text-[#3A3F4C] hover:bg-[#F7F8FA] active:bg-[#F0F1F4] border border-[#E4E6EC]",
};

const sizeClasses: Record<CleanButtonSize, string> = {
  sm: "h-8 px-3 text-[12px] font-medium gap-1.5 rounded-lg",
  md: "h-10 px-4 text-[13px] font-semibold gap-2 rounded-lg",
  lg: "h-11 px-5 text-[14px] font-semibold gap-2 rounded-xl",
};

export const CleanButton = forwardRef<HTMLButtonElement, CleanButtonProps>(
  (
    {
      variant = "primary",
      size = "md",
      fullWidth = false,
      icon,
      iconRight,
      className,
      children,
      disabled,
      ...props
    },
    ref,
  ) => {
    return (
      <button
        ref={ref}
        type="button"
        disabled={disabled}
        className={cn(
          "inline-flex items-center justify-center whitespace-nowrap select-none",
          "transition-[transform,background-color,border-color,box-shadow,color] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)]",
          "active:scale-[0.97]",
          "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#111217]/25 focus-visible:ring-offset-2",
          "disabled:opacity-50 disabled:pointer-events-none disabled:active:scale-100",
          variantClasses[variant],
          sizeClasses[size],
          fullWidth && "w-full",
          className,
        )}
        {...props}
      >
        {icon && <span className="shrink-0 [&>svg]:size-4">{icon}</span>}
        {children}
        {iconRight && <span className="shrink-0 [&>svg]:size-4">{iconRight}</span>}
      </button>
    );
  },
);

CleanButton.displayName = "CleanButton";