-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIconButton.tsx
More file actions
138 lines (131 loc) · 3.24 KB
/
Copy pathIconButton.tsx
File metadata and controls
138 lines (131 loc) · 3.24 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import type { VariantProps } from "class-variance-authority";
import { cva } from "class-variance-authority";
import type { ButtonHTMLAttributes, ReactNode } from "react";
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
const iconButtonVariants = cva(
"inline-flex cursor-pointer items-center justify-center transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-purple-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-600",
{
variants: {
size: {
small: "size-8",
medium: "size-9",
large: "size-11",
},
shape: {
circular: "rounded-full",
square: "rounded-md",
},
color: {
default: "",
purple: "",
},
variant: {
outlined: "border",
contained: "border-0",
ghost: "border border-transparent bg-transparent",
},
},
compoundVariants: [
// Default variants
{
variant: "contained",
color: "default",
class: "bg-gray-300 hover:bg-gray-200",
},
{
variant: "outlined",
color: "default",
class:
"border-gray-300 bg-white hover:border-purple-100 hover:bg-purple-100",
},
// purple variants
{
variant: "contained",
color: "purple",
class: "bg-purple-800 hover:bg-purple-600",
},
{
variant: "outlined",
color: "purple",
class:
"border-purple-800 bg-white hover:border-purple-100 hover:bg-purple-100",
},
// Ghost variants
{
variant: "ghost",
color: "default",
class: "text-gray-900 hover:bg-gray-100",
},
{
variant: "ghost",
color: "purple",
class: "text-purple-800 hover:bg-purple-50",
},
],
defaultVariants: {
variant: "outlined",
color: "default",
size: "medium",
shape: "square",
},
}
);
export interface IconButtonProps
extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "color">,
VariantProps<typeof iconButtonVariants> {
children: ReactNode;
loading?: boolean;
"aria-label": string;
}
const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
(
{
className,
size,
shape,
color,
variant,
loading,
children,
disabled,
type = "button",
...props
},
ref
) => {
const getSpinnerSize = () => {
if (size === "small") {
return "16px";
}
return "20px";
};
const spinnerSize = getSpinnerSize();
return (
<button
className={cn(
iconButtonVariants({ size, shape, color, variant }),
className
)}
disabled={disabled || loading}
ref={ref}
type={type}
{...props}
>
{loading ? (
<div
className="animate-spin rounded-full border-2 border-current border-t-transparent"
style={{
width: spinnerSize,
height: spinnerSize,
}}
/>
) : (
children
)}
</button>
);
}
);
IconButton.displayName = "IconButton";
export { IconButton, iconButtonVariants };