infinity-ui-elements 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,35 +1,308 @@
1
- import React from "react";
2
-
3
- interface ButtonProps {
4
- variant?: "primary" | "secondary";
5
- children: React.ReactNode;
6
- onClick?: () => void;
7
- disabled?: boolean;
8
- className?: string;
1
+ import * as React from "react";
2
+ import { Slot } from "@radix-ui/react-slot";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { PulseLoader, ClipLoader } from "react-spinners";
5
+
6
+ import { cn } from "../../lib/utils";
7
+
8
+ const buttonVariants = cva(
9
+ "items-center gap-3 justify-center whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ primary:
14
+ "bg-action-fill-primary-default text-action-ink-on-primary-normal hover:bg-action-fill-primary-hover",
15
+ secondary:
16
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
17
+ tertiary: "hover:bg-accent hover:text-accent-foreground",
18
+ },
19
+ color: {
20
+ primary: "",
21
+ positive: "",
22
+ negative: "",
23
+ notice: "",
24
+ info: "",
25
+ neutral: "",
26
+ },
27
+ size: {
28
+ xsmall: "md:h-[28px] px-3 text-xs rounded-medium",
29
+ small: "md:h-[32px] px-4 text-xs rounded-medium",
30
+ medium: "md:h-[36px] px-6 py-2 rounded-medium",
31
+ large: "md:h-[44px] px-6 text-base rounded-xlarge",
32
+ },
33
+ isIconOnly: {
34
+ true: "aspect-square p-0",
35
+ false: "",
36
+ },
37
+ isLoading: {
38
+ true: "cursor-not-allowed",
39
+ false: "",
40
+ },
41
+ isDisabled: {
42
+ true: "cursor-not-allowed",
43
+ false: "cursor-pointer",
44
+ },
45
+ isFullWidth: {
46
+ true: "flex w-full",
47
+ false: "flex w-fit",
48
+ },
49
+ },
50
+ compoundVariants: [
51
+ // Primary variant colors
52
+ {
53
+ variant: "primary",
54
+ color: "primary",
55
+ class: `bg-action-fill-primary-default text-action-ink-on-primary-normal
56
+ hover:bg-action-fill-primary-hover
57
+ disabled:bg-action-fill-primary-disabled
58
+ disabled:text-action-ink-primary-disabled
59
+ `,
60
+ },
61
+ {
62
+ variant: "primary",
63
+ color: "positive",
64
+ class: `bg-action-fill-positive-default text-action-ink-on-primary-normal
65
+ hover:bg-action-fill-positive-hover
66
+ disabled:bg-action-fill-primary-disabled
67
+ disabled:text-action-ink-primary-disabled
68
+ `,
69
+ },
70
+ {
71
+ variant: "primary",
72
+ color: "negative",
73
+ class: `bg-action-fill-negative-default text-action-ink-on-primary-normal
74
+ hover:bg-action-fill-negative-hover
75
+ disabled:bg-action-fill-negative-disabled
76
+ disabled:text-action-ink-negative-disabled
77
+ `,
78
+ },
79
+ {
80
+ variant: "primary",
81
+ color: "notice",
82
+ class: `bg-action-fill-notice-default text-action-ink-on-primary-normal
83
+ hover:bg-action-fill-notice-hover
84
+ disabled:bg-action-fill-notice-disabled
85
+ disabled:text-action-ink-notice-disabled
86
+ `,
87
+ },
88
+ {
89
+ variant: "primary",
90
+ color: "info",
91
+ class: `bg-action-fill-info-default text-action-ink-on-primary-normal
92
+ hover:bg-action-fill-info-hover
93
+ disabled:bg-action-fill-info-disabled
94
+ disabled:text-action-ink-info-disabled
95
+ `,
96
+ },
97
+ {
98
+ variant: "primary",
99
+ color: "neutral",
100
+ class: `bg-action-fill-neutral-default text-action-ink-on-primary-normal
101
+ hover:bg-action-fill-neutral-hover
102
+ disabled:bg-action-fill-neutral-disabled
103
+ disabled:text-action-ink-neutral-disabled
104
+ `,
105
+ },
106
+ // Secondary variant colors
107
+ {
108
+ variant: "secondary",
109
+ color: "primary",
110
+ class: `border-action-outline-info-faded text-action-ink-primary-normal hover:border-action-outline-info-faded-hover
111
+ disabled:bg-action-outline-info-disabled
112
+ disabled:text-action-ink-primary-disabled
113
+ disabled:border-action-outline-primary-disabled
114
+ `,
115
+ },
116
+ {
117
+ variant: "secondary",
118
+ color: "positive",
119
+ class:
120
+ "border-action-outline-positive-faded text-action-ink-positive-normal hover:border-action-outline-positive-faded-hover disabled:bg-action-outline-positive-disabled",
121
+ },
122
+ {
123
+ variant: "secondary",
124
+ color: "negative",
125
+ class:
126
+ "border-action-outline-negative-faded text-action-ink-negative-normal hover:border-action-outline-negative-faded-hover disabled:bg-action-outline-negative-disabled",
127
+ },
128
+ {
129
+ variant: "secondary",
130
+ color: "notice",
131
+ class:
132
+ "border-action-outline-notice-faded text-action-ink-notice-normal hover:border-action-outline-notice-faded-hover disabled:bg-action-outline-notice-disabled",
133
+ },
134
+ {
135
+ variant: "secondary",
136
+ color: "info",
137
+ class:
138
+ "border-action-outline-info-faded text-action-ink-info-normal hover:border-action-outline-info-faded-hover disabled:bg-action-outline-info-disabled",
139
+ },
140
+ {
141
+ variant: "secondary",
142
+ color: "neutral",
143
+ class:
144
+ "border-action-outline-neutral-faded text-action-ink-neutral-normal hover:bg-action-outline-neutral-faded-hover",
145
+ },
146
+ // Tertiary variant colors
147
+ {
148
+ variant: "tertiary",
149
+ color: "primary",
150
+ class: `text-action-ink-primary-normal
151
+ hover:bg-action-fill-primary-faded
152
+ disabled:text-action-ink-on-primary-muted
153
+ `,
154
+ },
155
+ {
156
+ variant: "tertiary",
157
+ color: "positive",
158
+ class: `text-action-ink-positive-normal
159
+ hover:bg-action-fill-positive-faded
160
+ disabled:text-action-ink-on-positive-muted
161
+ `,
162
+ },
163
+ {
164
+ variant: "tertiary",
165
+ color: "negative",
166
+ class: `text-action-ink-negative-normal
167
+ hover:bg-action-fill-negative-faded
168
+ disabled:text-action-ink-on-negative-muted
169
+ `,
170
+ },
171
+ {
172
+ variant: "tertiary",
173
+ color: "notice",
174
+ class: `text-action-ink-notice-normal
175
+ hover:bg-action-fill-notice-faded
176
+ disabled:text-action-ink-on-notice-muted
177
+ `,
178
+ },
179
+ {
180
+ variant: "tertiary",
181
+ color: "info",
182
+ class: `text-action-ink-info-normal
183
+ hover:bg-action-fill-info-faded
184
+ disabled:text-action-ink-on-notice-muted
185
+ `,
186
+ },
187
+ {
188
+ variant: "tertiary",
189
+ color: "neutral",
190
+ class: `text-action-ink-neutral-normal
191
+ hover:bg-action-fill-neutral-faded
192
+ disabled:text-action-ink-on-notice-muted
193
+ `,
194
+ },
195
+ // Icon only sizing
196
+ {
197
+ isIconOnly: true,
198
+ size: "xsmall",
199
+ class: "h-7 w-7",
200
+ },
201
+ {
202
+ isIconOnly: true,
203
+ size: "small",
204
+ class: "h-8 w-8",
205
+ },
206
+ {
207
+ isIconOnly: true,
208
+ size: "medium",
209
+ class: "h-9 w-9",
210
+ },
211
+ {
212
+ isIconOnly: true,
213
+ size: "large",
214
+ class: "h-10 w-10",
215
+ },
216
+ ],
217
+ defaultVariants: {
218
+ variant: "primary",
219
+ color: "primary",
220
+ size: "medium",
221
+ isIconOnly: false,
222
+ isLoading: false,
223
+ isFullWidth: false,
224
+ },
225
+ }
226
+ );
227
+
228
+ export interface ButtonProps
229
+ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color">,
230
+ VariantProps<typeof buttonVariants> {
231
+ asChild?: boolean;
232
+ leadingIcon?: React.ReactNode;
233
+ trailingIcon?: React.ReactNode;
234
+ isFullWidth?: boolean;
9
235
  }
10
236
 
11
- export const Button: React.FC<ButtonProps> = ({
12
- variant = "primary",
13
- children,
14
- onClick,
15
- disabled = false,
16
- className = "",
17
- }) => {
18
- const baseClasses =
19
- "px-4 py-2 rounded font-semibold transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2";
20
-
21
- const variantClasses = {
22
- primary:
23
- "bg-primary text-white hover:bg-blue-600 focus:ring-primary disabled:bg-gray-400 disabled:cursor-not-allowed",
24
- secondary:
25
- "bg-secondary text-white hover:bg-gray-600 focus:ring-secondary disabled:bg-gray-400 disabled:cursor-not-allowed",
26
- };
27
-
28
- const combinedClasses = `${baseClasses} ${variantClasses[variant]} ${className}`;
29
-
30
- return (
31
- <button className={combinedClasses} onClick={onClick} disabled={disabled}>
32
- {children}
33
- </button>
34
- );
35
- };
237
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
238
+ (
239
+ {
240
+ className,
241
+ variant = "primary",
242
+ color = "primary",
243
+ size,
244
+ isIconOnly,
245
+ isLoading,
246
+ asChild = false,
247
+ leadingIcon,
248
+ trailingIcon,
249
+ isFullWidth = false,
250
+ children,
251
+ disabled,
252
+ ...props
253
+ },
254
+ ref
255
+ ) => {
256
+ const Comp = asChild ? Slot : "button";
257
+
258
+ const isDisabled = disabled || isLoading || false;
259
+
260
+ const buttonContent = (
261
+ <>
262
+ {isLoading && !isIconOnly && (
263
+ <PulseLoader
264
+ color={`var(--color-action-ink-${color}-normal)`}
265
+ size={10}
266
+ />
267
+ )}
268
+ {isLoading && isIconOnly && (
269
+ <ClipLoader
270
+ color={`var(--color-action-ink-${color}-normal)`}
271
+ size={20}
272
+ />
273
+ )}
274
+ {!isLoading && leadingIcon && (
275
+ <span className="mr-2">{leadingIcon}</span>
276
+ )}
277
+ {!isIconOnly && !isLoading && children}
278
+ {isIconOnly && !isLoading && children}
279
+ {!isLoading && trailingIcon && <span>{trailingIcon}</span>}
280
+ </>
281
+ );
282
+
283
+ return (
284
+ <Comp
285
+ className={cn(
286
+ buttonVariants({
287
+ variant,
288
+ color,
289
+ size,
290
+ isIconOnly,
291
+ isLoading,
292
+ isDisabled,
293
+ isFullWidth,
294
+ }),
295
+ className
296
+ )}
297
+ ref={ref}
298
+ disabled={isDisabled}
299
+ {...props}
300
+ >
301
+ {buttonContent}
302
+ </Comp>
303
+ );
304
+ }
305
+ );
306
+ Button.displayName = "Button";
307
+
308
+ export { Button, buttonVariants };
@@ -1 +1,2 @@
1
- export { Button } from "./Button";
1
+ export { Button, buttonVariants } from "./Button";
2
+ export type { ButtonProps } from "./Button";