1.6 KB74 lines
Blame
1import { forwardRef } from "react";
2
3const variantStyles = {
4 primary: {
5 backgroundColor: "var(--accent)",
6 color: "var(--accent-text)",
7 },
8 secondary: {
9 backgroundColor: "var(--bg-inset)",
10 border: "1px solid var(--border)",
11 color: "var(--text-secondary)",
12 },
13 ghost: {
14 background: "none",
15 border: "none",
16 color: "var(--accent)",
17 },
18 danger: {
19 backgroundColor: "var(--status-closed-bg)",
20 border: "1px solid var(--status-closed-border)",
21 color: "var(--status-closed-text)",
22 },
23} as const;
24
25const sizeClasses = {
26 sm: "text-sm px-3 py-1",
27 md: "text-sm px-3 py-1.5",
28} as const;
29
30export interface ButtonProps
31 extends React.ButtonHTMLAttributes<HTMLButtonElement> {
32 variant?: keyof typeof variantStyles;
33 size?: "sm" | "md";
34 loading?: boolean;
35 loadingText?: string;
36}
37
38export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
39 function Button(
40 {
41 variant = "primary",
42 size = "sm",
43 loading = false,
44 loadingText,
45 disabled,
46 className = "",
47 style,
48 children,
49 ...props
50 },
51 ref
52 ) {
53 const isDisabled = disabled || loading;
54
55 return (
56 <button
57 ref={ref}
58 disabled={isDisabled}
59 className={`${sizeClasses[size]} ${className}`}
60 style={{
61 ...variantStyles[variant],
62 opacity: isDisabled ? 0.5 : 1,
63 cursor: loading ? "wait" : isDisabled ? "default" : "pointer",
64 font: "inherit",
65 ...style,
66 }}
67 {...props}
68 >
69 {loading && loadingText ? loadingText : children}
70 </button>
71 );
72 }
73);
74