banhaten 0.1.0 → 0.1.2

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.
Files changed (81) hide show
  1. package/README.md +21 -9
  2. package/package.json +8 -2
  3. package/registry/components/accordion.tsx +37 -1
  4. package/registry/components/alert.tsx +14 -28
  5. package/registry/components/attribute.tsx +6 -10
  6. package/registry/components/autocomplete.tsx +637 -0
  7. package/registry/components/avatar.tsx +259 -24
  8. package/registry/components/badge.tsx +97 -35
  9. package/registry/components/button-group.tsx +1 -1
  10. package/registry/components/card.tsx +1 -1
  11. package/registry/components/checkbox.tsx +19 -16
  12. package/registry/components/date-picker-state.ts +253 -0
  13. package/registry/components/date-picker.tsx +115 -158
  14. package/registry/components/expanded/ActivityFeed.tsx +37 -23
  15. package/registry/components/expanded/Banner.tsx +54 -19
  16. package/registry/components/expanded/Breadcrumbs.tsx +10 -38
  17. package/registry/components/expanded/CatalogComponentsShowcase.tsx +11 -16
  18. package/registry/components/expanded/CatalogTag.tsx +4 -11
  19. package/registry/components/expanded/CommandBar.tsx +33 -53
  20. package/registry/components/expanded/EmptyState.tsx +155 -0
  21. package/registry/components/expanded/FileUpload.tsx +362 -59
  22. package/registry/components/expanded/OnboardingStepListItem.tsx +6 -10
  23. package/registry/components/expanded/PageHeader.tsx +2 -11
  24. package/registry/components/expanded/Slideout.tsx +12 -23
  25. package/registry/components/expanded/Steps.tsx +6 -8
  26. package/registry/components/expanded/Table.tsx +18 -40
  27. package/registry/components/expanded/Timeline.tsx +5 -24
  28. package/registry/components/expanded/activityFeed.css +10 -54
  29. package/registry/components/expanded/banner.css +8 -75
  30. package/registry/components/expanded/breadcrumbs.css +1 -1
  31. package/registry/components/expanded/commandBar.css +23 -26
  32. package/registry/components/expanded/divider.css +1 -1
  33. package/registry/components/expanded/emptyState.css +111 -0
  34. package/registry/components/expanded/fileUpload.css +304 -75
  35. package/registry/components/expanded/pageHeader.css +1 -1
  36. package/registry/components/expanded/slideout.css +1 -0
  37. package/registry/components/expanded/steps.css +15 -51
  38. package/registry/components/expanded/table.css +6 -1
  39. package/registry/components/expanded/timeline.css +18 -15
  40. package/registry/components/input-otp.tsx +574 -0
  41. package/registry/components/input.tsx +140 -59
  42. package/registry/components/menu.tsx +470 -80
  43. package/registry/components/pagination.tsx +6 -18
  44. package/registry/components/popover.tsx +840 -0
  45. package/registry/components/radio-card.tsx +25 -31
  46. package/registry/components/select-content.tsx +28 -123
  47. package/registry/components/select.tsx +13 -9
  48. package/registry/components/skeleton.css +57 -0
  49. package/registry/components/skeleton.tsx +482 -0
  50. package/registry/components/social-button.tsx +24 -90
  51. package/registry/components/spinner.tsx +91 -7
  52. package/registry/components/textarea.tsx +21 -36
  53. package/registry/components/toggle.tsx +7 -23
  54. package/registry/components/tooltip.tsx +8 -4
  55. package/registry/examples/attribute-demo.tsx +2 -2
  56. package/registry/examples/autocomplete-demo.tsx +109 -0
  57. package/registry/examples/avatar-demo.tsx +102 -47
  58. package/registry/examples/badge-demo.tsx +16 -0
  59. package/registry/examples/checkbox-demo.tsx +3 -8
  60. package/registry/examples/date-picker-demo.tsx +75 -22
  61. package/registry/examples/expanded/banner-demo.tsx +31 -6
  62. package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -0
  63. package/registry/examples/expanded/command-bar-demo.tsx +236 -0
  64. package/registry/examples/expanded/empty-state-demo.tsx +39 -0
  65. package/registry/examples/expanded/file-upload-demo.tsx +60 -0
  66. package/registry/examples/expanded/steps-demo.tsx +11 -0
  67. package/registry/examples/expanded/table-demo.tsx +142 -0
  68. package/registry/examples/input-demo.tsx +1 -1
  69. package/registry/examples/input-otp-demo.tsx +72 -0
  70. package/registry/examples/menu-demo.tsx +101 -88
  71. package/registry/examples/popover-demo.tsx +546 -0
  72. package/registry/examples/progress-demo.tsx +2 -2
  73. package/registry/examples/select-demo.tsx +32 -18
  74. package/registry/examples/skeleton-demo.tsx +56 -0
  75. package/registry/examples/social-button-demo.tsx +33 -33
  76. package/registry/examples/spinner-demo.tsx +59 -0
  77. package/registry/examples/tag-demo.tsx +1 -1
  78. package/registry/examples/textarea-demo.tsx +1 -1
  79. package/registry/index.json +266 -20
  80. package/registry/styles/globals.css +93 -3
  81. package/src/cli/index.js +997 -62
@@ -0,0 +1,482 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ import "./skeleton.css"
7
+
8
+ const skeletonVariants = cva(
9
+ "relative block min-w-0 shrink-0 overflow-hidden bg-[var(--bh-skeleton-bg)] h-[var(--bh-skeleton-height)] w-[var(--bh-skeleton-width)]",
10
+ {
11
+ variants: {
12
+ shape: {
13
+ block:
14
+ "rounded-[var(--bh-skeleton-radius)] [--bh-skeleton-radius:var(--bh-radius-md-6)]",
15
+ text:
16
+ "rounded-[var(--bh-radius-full)] [--bh-skeleton-height:var(--bh-text-body-md-regular-line-height)]",
17
+ circle:
18
+ "aspect-square rounded-[var(--bh-radius-full)] [--bh-skeleton-height:var(--bh-skeleton-width)]",
19
+ },
20
+ size: {
21
+ xs: "[--bh-skeleton-height:var(--bh-space-md-8)]",
22
+ sm: "[--bh-skeleton-height:var(--bh-space-xl-12)]",
23
+ md: "[--bh-skeleton-height:var(--bh-space-3xl-16)]",
24
+ lg: "[--bh-skeleton-height:var(--bh-space-5xl-24)]",
25
+ xl: "[--bh-skeleton-height:var(--bh-space-7xl-40)]",
26
+ },
27
+ tone: {
28
+ default:
29
+ "[--bh-skeleton-bg:var(--bh-bg-muted)] [--bh-skeleton-highlight:var(--bh-bg-raised-subtle)]",
30
+ subtle:
31
+ "[--bh-skeleton-bg:var(--bh-bg-subtle)] [--bh-skeleton-highlight:var(--bh-bg-default-hover)]",
32
+ surface:
33
+ "[--bh-skeleton-bg:var(--bh-bg-raised-subtle)] [--bh-skeleton-highlight:var(--bh-bg-default)]",
34
+ brand:
35
+ "[--bh-skeleton-bg:var(--bh-bg-brand-subtle)] [--bh-skeleton-highlight:var(--bh-bg-brand-soft)]",
36
+ },
37
+ },
38
+ defaultVariants: {
39
+ shape: "block",
40
+ size: "md",
41
+ tone: "default",
42
+ },
43
+ }
44
+ )
45
+
46
+ type SkeletonCssProperties = React.CSSProperties & {
47
+ "--bh-skeleton-height"?: React.CSSProperties["height"]
48
+ "--bh-skeleton-width"?: React.CSSProperties["width"]
49
+ }
50
+
51
+ type SkeletonProps = React.ComponentProps<"span"> &
52
+ VariantProps<typeof skeletonVariants> & {
53
+ animated?: boolean
54
+ }
55
+
56
+ const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(function Skeleton(
57
+ {
58
+ animated = true,
59
+ "aria-hidden": ariaHidden = true,
60
+ className,
61
+ shape,
62
+ size,
63
+ tone,
64
+ ...props
65
+ },
66
+ ref
67
+ ) {
68
+ return (
69
+ <span
70
+ aria-hidden={ariaHidden}
71
+ data-animated={animated ? "true" : "false"}
72
+ data-slot="skeleton"
73
+ ref={ref}
74
+ className={cn(skeletonVariants({ shape, size, tone, className }))}
75
+ {...props}
76
+ />
77
+ )
78
+ })
79
+
80
+ type SkeletonTextProps = Omit<React.ComponentProps<"div">, "children"> & {
81
+ animated?: boolean
82
+ lineCount?: number
83
+ lineSize?: SkeletonProps["size"]
84
+ tone?: SkeletonProps["tone"]
85
+ widths?: Array<React.CSSProperties["width"]>
86
+ }
87
+
88
+ function SkeletonText({
89
+ animated,
90
+ className,
91
+ lineCount = 3,
92
+ lineSize = "md",
93
+ tone,
94
+ widths,
95
+ ...props
96
+ }: SkeletonTextProps) {
97
+ const count = Math.max(1, lineCount)
98
+
99
+ return (
100
+ <div
101
+ aria-hidden="true"
102
+ data-slot="skeleton-text"
103
+ className={cn("grid gap-[var(--bh-space-xs-4)]", className)}
104
+ {...props}
105
+ >
106
+ {Array.from({ length: count }, (_, index) => {
107
+ const width =
108
+ widths?.[index] ?? (index === count - 1 && count > 1 ? "66%" : "100%")
109
+
110
+ return (
111
+ <Skeleton
112
+ animated={animated}
113
+ key={index}
114
+ shape="text"
115
+ size={lineSize}
116
+ tone={tone}
117
+ style={{ "--bh-skeleton-width": width } as SkeletonCssProperties}
118
+ />
119
+ )
120
+ })}
121
+ </div>
122
+ )
123
+ }
124
+
125
+ const skeletonAvatarSizes = {
126
+ xs: "size-[var(--bh-space-5xl-24)]",
127
+ sm: "size-[var(--bh-space-6xl-32)]",
128
+ md: "size-[var(--bh-space-7xl-40)]",
129
+ lg: "size-[var(--bh-space-8xl-48)]",
130
+ xl: "size-[var(--bh-space-9xl-64)]",
131
+ } as const
132
+
133
+ type SkeletonAvatarProps = Omit<SkeletonProps, "shape" | "size"> & {
134
+ size?: keyof typeof skeletonAvatarSizes
135
+ }
136
+
137
+ function SkeletonAvatar({
138
+ className,
139
+ size = "md",
140
+ ...props
141
+ }: SkeletonAvatarProps) {
142
+ return (
143
+ <Skeleton
144
+ shape="circle"
145
+ className={cn(skeletonAvatarSizes[size], className)}
146
+ {...props}
147
+ />
148
+ )
149
+ }
150
+
151
+ const skeletonButtonSizes = {
152
+ sm: "h-[var(--bh-button-sm-height)] w-[var(--bh-space-11xl-96)]",
153
+ default: "h-[var(--bh-button-md-height)] w-[var(--bh-space-12xl-128)]",
154
+ lg: "h-[var(--bh-button-lg-height)] w-[var(--bh-space-13xl-160)]",
155
+ xl: "h-[var(--bh-button-xl-height)] w-[var(--bh-space-14xl-192)]",
156
+ icon: "size-[var(--bh-button-md-height)]",
157
+ } as const
158
+
159
+ type SkeletonButtonProps = Omit<SkeletonProps, "shape" | "size"> & {
160
+ size?: keyof typeof skeletonButtonSizes
161
+ }
162
+
163
+ function SkeletonButton({
164
+ className,
165
+ size = "default",
166
+ ...props
167
+ }: SkeletonButtonProps) {
168
+ return (
169
+ <Skeleton
170
+ shape="block"
171
+ className={cn(
172
+ "rounded-[var(--bh-control-default)]",
173
+ skeletonButtonSizes[size],
174
+ className
175
+ )}
176
+ {...props}
177
+ />
178
+ )
179
+ }
180
+
181
+ type SkeletonInputProps = Omit<React.ComponentProps<"div">, "children"> & {
182
+ animated?: boolean
183
+ helper?: boolean
184
+ label?: boolean
185
+ tone?: SkeletonProps["tone"]
186
+ }
187
+
188
+ function SkeletonInput({
189
+ animated,
190
+ className,
191
+ helper = true,
192
+ label = true,
193
+ tone,
194
+ ...props
195
+ }: SkeletonInputProps) {
196
+ return (
197
+ <div
198
+ aria-hidden="true"
199
+ data-slot="skeleton-input"
200
+ className={cn("grid gap-[var(--bh-space-sm-6)]", className)}
201
+ {...props}
202
+ >
203
+ {label && (
204
+ <Skeleton
205
+ animated={animated}
206
+ shape="text"
207
+ size="sm"
208
+ tone={tone}
209
+ style={{ "--bh-skeleton-width": "42%" } as SkeletonCssProperties}
210
+ />
211
+ )}
212
+ <Skeleton
213
+ animated={animated}
214
+ className="rounded-[var(--bh-control-default)]"
215
+ size="xl"
216
+ tone={tone}
217
+ />
218
+ {helper && (
219
+ <Skeleton
220
+ animated={animated}
221
+ shape="text"
222
+ size="xs"
223
+ tone={tone}
224
+ style={{ "--bh-skeleton-width": "58%" } as SkeletonCssProperties}
225
+ />
226
+ )}
227
+ </div>
228
+ )
229
+ }
230
+
231
+ type SkeletonCardProps = Omit<React.ComponentProps<"div">, "children"> & {
232
+ actions?: boolean
233
+ animated?: boolean
234
+ avatar?: boolean
235
+ lines?: number
236
+ media?: boolean
237
+ tone?: SkeletonProps["tone"]
238
+ }
239
+
240
+ function SkeletonCard({
241
+ actions = true,
242
+ animated,
243
+ avatar = true,
244
+ className,
245
+ lines = 3,
246
+ media = true,
247
+ tone,
248
+ ...props
249
+ }: SkeletonCardProps) {
250
+ return (
251
+ <div
252
+ aria-hidden="true"
253
+ data-slot="skeleton-card"
254
+ className={cn(
255
+ "grid gap-[var(--bh-space-4xl-20)] rounded-[var(--bh-radius-xl-10)] border border-[var(--bh-border-default)] bg-[var(--bh-bg-raised)] p-[var(--bh-card-desktop-content-padding)] shadow-[var(--shadow-component-default)]",
256
+ className
257
+ )}
258
+ {...props}
259
+ >
260
+ {media && (
261
+ <Skeleton
262
+ animated={animated}
263
+ className="aspect-[16/9] rounded-[var(--bh-radius-lg-8)]"
264
+ size="xl"
265
+ tone={tone}
266
+ />
267
+ )}
268
+ <div className="grid grid-cols-[auto_minmax(0,1fr)] gap-[var(--bh-space-xl-12)]">
269
+ {avatar && <SkeletonAvatar animated={animated} tone={tone} />}
270
+ <SkeletonText animated={animated} lineCount={lines} tone={tone} />
271
+ </div>
272
+ {actions && (
273
+ <div className="flex flex-wrap gap-[var(--bh-space-md-8)]">
274
+ <SkeletonButton animated={animated} size="sm" tone={tone} />
275
+ <SkeletonButton animated={animated} size="sm" tone={tone} />
276
+ </div>
277
+ )}
278
+ </div>
279
+ )
280
+ }
281
+
282
+ type SkeletonListProps = Omit<React.ComponentProps<"div">, "children"> & {
283
+ animated?: boolean
284
+ rows?: number
285
+ tone?: SkeletonProps["tone"]
286
+ withAvatar?: boolean
287
+ withMeta?: boolean
288
+ }
289
+
290
+ function SkeletonList({
291
+ animated,
292
+ className,
293
+ rows = 4,
294
+ tone,
295
+ withAvatar = true,
296
+ withMeta = true,
297
+ ...props
298
+ }: SkeletonListProps) {
299
+ const rowCount = Math.max(1, rows)
300
+
301
+ return (
302
+ <div
303
+ aria-hidden="true"
304
+ data-slot="skeleton-list"
305
+ className={cn(
306
+ "overflow-hidden rounded-[var(--bh-radius-lg-8)] border border-[var(--bh-border-default)] bg-[var(--bh-bg-raised)]",
307
+ className
308
+ )}
309
+ {...props}
310
+ >
311
+ {Array.from({ length: rowCount }, (_, index) => (
312
+ <div
313
+ className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-[var(--bh-space-xl-12)] border-b border-[var(--bh-border-subtle)] p-[var(--bh-space-3xl-16)] last:border-b-0"
314
+ key={index}
315
+ >
316
+ {withAvatar && <SkeletonAvatar animated={animated} size="sm" tone={tone} />}
317
+ <SkeletonText
318
+ animated={animated}
319
+ lineCount={2}
320
+ lineSize="sm"
321
+ tone={tone}
322
+ widths={["74%", "46%"]}
323
+ />
324
+ {withMeta && (
325
+ <Skeleton
326
+ animated={animated}
327
+ shape="text"
328
+ size="sm"
329
+ tone={tone}
330
+ style={{ "--bh-skeleton-width": "64%" } as SkeletonCssProperties}
331
+ />
332
+ )}
333
+ </div>
334
+ ))}
335
+ </div>
336
+ )
337
+ }
338
+
339
+ type SkeletonTableProps = Omit<React.ComponentProps<"div">, "children"> & {
340
+ animated?: boolean
341
+ columns?: number
342
+ rows?: number
343
+ showHeader?: boolean
344
+ tone?: SkeletonProps["tone"]
345
+ }
346
+
347
+ function SkeletonTable({
348
+ animated,
349
+ className,
350
+ columns = 4,
351
+ rows = 5,
352
+ showHeader = true,
353
+ tone,
354
+ ...props
355
+ }: SkeletonTableProps) {
356
+ const columnCount = Math.max(1, columns)
357
+ const rowCount = Math.max(1, rows)
358
+ const gridStyle = {
359
+ "--bh-skeleton-table-columns": `repeat(${columnCount}, minmax(0, 1fr))`,
360
+ } as React.CSSProperties
361
+
362
+ return (
363
+ <div
364
+ aria-hidden="true"
365
+ data-slot="skeleton-table"
366
+ className={cn(
367
+ "overflow-hidden rounded-[var(--bh-radius-lg-8)] border border-[var(--bh-border-default)] bg-[var(--bh-bg-raised)]",
368
+ className
369
+ )}
370
+ {...props}
371
+ >
372
+ {showHeader && (
373
+ <div
374
+ className="grid grid-cols-[var(--bh-skeleton-table-columns)] gap-[var(--bh-space-3xl-16)] border-b border-[var(--bh-border-default)] bg-[var(--bh-bg-muted)] p-[var(--bh-space-xl-12)]"
375
+ style={gridStyle}
376
+ >
377
+ {Array.from({ length: columnCount }, (_, index) => (
378
+ <Skeleton
379
+ animated={animated}
380
+ key={index}
381
+ shape="text"
382
+ size="sm"
383
+ tone={tone}
384
+ />
385
+ ))}
386
+ </div>
387
+ )}
388
+ {Array.from({ length: rowCount }, (_, rowIndex) => (
389
+ <div
390
+ className="grid grid-cols-[var(--bh-skeleton-table-columns)] items-center gap-[var(--bh-space-3xl-16)] border-b border-[var(--bh-border-subtle)] p-[var(--bh-space-xl-12)] last:border-b-0"
391
+ key={rowIndex}
392
+ style={gridStyle}
393
+ >
394
+ {Array.from({ length: columnCount }, (_, columnIndex) => (
395
+ <Skeleton
396
+ animated={animated}
397
+ key={columnIndex}
398
+ shape="text"
399
+ size="sm"
400
+ tone={tone}
401
+ style={
402
+ {
403
+ "--bh-skeleton-width":
404
+ columnIndex === columnCount - 1 ? "58%" : "100%",
405
+ } as SkeletonCssProperties
406
+ }
407
+ />
408
+ ))}
409
+ </div>
410
+ ))}
411
+ </div>
412
+ )
413
+ }
414
+
415
+ type SkeletonFormProps = Omit<React.ComponentProps<"div">, "children"> & {
416
+ actions?: boolean
417
+ animated?: boolean
418
+ fields?: number
419
+ tone?: SkeletonProps["tone"]
420
+ }
421
+
422
+ function SkeletonForm({
423
+ actions = true,
424
+ animated,
425
+ className,
426
+ fields = 3,
427
+ tone,
428
+ ...props
429
+ }: SkeletonFormProps) {
430
+ const fieldCount = Math.max(1, fields)
431
+
432
+ return (
433
+ <div
434
+ aria-hidden="true"
435
+ data-slot="skeleton-form"
436
+ className={cn(
437
+ "grid gap-[var(--bh-space-4xl-20)] rounded-[var(--bh-radius-lg-8)] border border-[var(--bh-border-default)] bg-[var(--bh-bg-raised)] p-[var(--bh-space-5xl-24)]",
438
+ className
439
+ )}
440
+ {...props}
441
+ >
442
+ {Array.from({ length: fieldCount }, (_, index) => (
443
+ <SkeletonInput
444
+ animated={animated}
445
+ helper={index === fieldCount - 1}
446
+ key={index}
447
+ tone={tone}
448
+ />
449
+ ))}
450
+ {actions && (
451
+ <div className="flex flex-wrap justify-end gap-[var(--bh-space-md-8)]">
452
+ <SkeletonButton animated={animated} size="sm" tone={tone} />
453
+ <SkeletonButton animated={animated} tone={tone} />
454
+ </div>
455
+ )}
456
+ </div>
457
+ )
458
+ }
459
+
460
+ export {
461
+ Skeleton,
462
+ SkeletonAvatar,
463
+ SkeletonButton,
464
+ SkeletonCard,
465
+ SkeletonForm,
466
+ SkeletonInput,
467
+ SkeletonList,
468
+ SkeletonTable,
469
+ SkeletonText,
470
+ skeletonVariants,
471
+ }
472
+ export type {
473
+ SkeletonAvatarProps,
474
+ SkeletonButtonProps,
475
+ SkeletonCardProps,
476
+ SkeletonFormProps,
477
+ SkeletonInputProps,
478
+ SkeletonListProps,
479
+ SkeletonProps,
480
+ SkeletonTableProps,
481
+ SkeletonTextProps,
482
+ }
@@ -1,6 +1,15 @@
1
1
  import * as React from "react"
2
2
  import { Slot } from "@radix-ui/react-slot"
3
3
  import { cva, type VariantProps } from "class-variance-authority"
4
+ import {
5
+ AppleIcon,
6
+ ChromeIcon,
7
+ FacebookIcon,
8
+ LinkedinIcon,
9
+ MessageCircleIcon,
10
+ TwitterIcon,
11
+ type LucideIcon,
12
+ } from "lucide-react"
4
13
 
5
14
  import { cn } from "@/lib/utils"
6
15
 
@@ -34,7 +43,7 @@ type SocialPlatformConfig = {
34
43
  const socialPlatformConfig: Record<SocialPlatform, SocialPlatformConfig> = {
35
44
  apple: {
36
45
  label: "Sign in with Apple",
37
- labelAr: "تسجيل الدخول باستخدام آبل",
46
+ labelAr: "تسجيل الدخول بأبل",
38
47
  solidBg: "var(--bh-social-apple-bg)",
39
48
  solidHover: "var(--bh-social-apple-hover)",
40
49
  solidBorder: "var(--bh-social-apple-border)",
@@ -46,7 +55,7 @@ const socialPlatformConfig: Record<SocialPlatform, SocialPlatformConfig> = {
46
55
  },
47
56
  facebook: {
48
57
  label: "Sign in with Facebook",
49
- labelAr: "تسجيل الدخول باستخدام فيسبوك",
58
+ labelAr: "تسجيل الدخول بفيسبوك",
50
59
  solidBg: "var(--bh-social-facebook-bg)",
51
60
  solidHover: "var(--bh-social-facebook-hover)",
52
61
  solidBorder: "transparent",
@@ -57,7 +66,7 @@ const socialPlatformConfig: Record<SocialPlatform, SocialPlatformConfig> = {
57
66
  },
58
67
  google: {
59
68
  label: "Sign in with Google",
60
- labelAr: "تسجيل الدخول باستخدام جوجل",
69
+ labelAr: "تسجيل الدخول بجوجل",
61
70
  solidBg: "var(--bh-social-google-bg)",
62
71
  solidHover: "var(--bh-social-google-hover)",
63
72
  solidBorder: "var(--bh-social-google-border)",
@@ -159,7 +168,7 @@ const SocialButton = React.forwardRef<HTMLButtonElement, SocialButtonProps>(func
159
168
  const cssVars = getSocialButtonVars(config, selectedVariant, isIcon)
160
169
  const content = (
161
170
  <>
162
- <SocialButtonIcon platform={platform} variant={selectedVariant} />
171
+ <SocialButtonIcon platform={platform} />
163
172
  {!isIcon && (
164
173
  <span
165
174
  data-slot="social-button-label"
@@ -250,105 +259,30 @@ function getSocialButtonVars(
250
259
 
251
260
  function SocialButtonIcon({
252
261
  platform,
253
- variant,
254
262
  }: {
255
263
  platform: SocialPlatform
256
- variant: SocialButtonVariant
257
264
  }) {
258
- const color =
259
- platform === "google" ? undefined : "var(--bh-social-button-icon)"
265
+ const Icon = socialButtonIcons[platform]
260
266
 
261
267
  return (
262
- <svg
268
+ <Icon
263
269
  aria-hidden="true"
264
270
  className="size-[var(--bh-social-button-icon-size)]"
265
271
  data-slot="social-button-icon"
266
- fill="none"
267
272
  focusable="false"
268
- viewBox="0 0 18 18"
269
- >
270
- {platform === "apple" && <AppleIcon color={color} />}
271
- {platform === "facebook" && <FacebookIcon color={color} />}
272
- {platform === "google" && <GoogleIcon />}
273
- {platform === "linkedin" && <LinkedInIcon color={color} />}
274
- {platform === "twitter" && <TwitterIcon color={color} />}
275
- {platform === "whatsapp" && <WhatsAppIcon color={color} />}
276
- </svg>
277
- )
278
- }
279
-
280
- function AppleIcon({ color }: { color?: string }) {
281
- return (
282
- <path
283
- d="M13.54 9.55c-.02-1.86 1.52-2.75 1.59-2.79-.87-1.27-2.22-1.44-2.7-1.46-1.15-.12-2.24.68-2.82.68-.59 0-1.49-.66-2.45-.64-1.26.02-2.42.73-3.07 1.86-1.31 2.27-.34 5.63.94 7.47.62.9 1.37 1.91 2.35 1.87.94-.04 1.3-.61 2.44-.61 1.13 0 1.46.61 2.45.59 1.01-.02 1.66-.92 2.28-1.82.72-1.05 1.02-2.07 1.03-2.12-.02-.01-1.99-.76-2.03-3.03ZM11.68 4.1c.52-.63.87-1.5.77-2.37-.74.03-1.64.49-2.17 1.12-.48.55-.9 1.44-.79 2.29.83.06 1.67-.42 2.19-1.04Z"
284
- fill={color}
285
- />
286
- )
287
- }
288
-
289
- function FacebookIcon({ color }: { color?: string }) {
290
- return (
291
- <path
292
- d="M18 9A9 9 0 1 0 7.59 17.9v-6.3H5.3V9h2.29V6.98c0-2.27 1.35-3.52 3.42-3.52.99 0 2.02.18 2.02.18v2.22h-1.14c-1.12 0-1.47.7-1.47 1.41V9h2.51l-.4 2.6h-2.11v6.3A9 9 0 0 0 18 9Z"
293
- fill={color}
294
- />
295
- )
296
- }
297
-
298
- function GoogleIcon() {
299
- return (
300
- <>
301
- <path
302
- d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"
303
- fill="var(--bh-social-google-blue)"
304
- />
305
- <path
306
- d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.35 0-4.34-1.59-5.05-3.72H.93v2.33A9 9 0 0 0 9 18Z"
307
- fill="var(--bh-social-google-green)"
308
- />
309
- <path
310
- d="M3.95 10.7A5.41 5.41 0 0 1 3.66 9c0-.59.1-1.16.29-1.7V4.97H.93A9 9 0 0 0 0 9c0 1.45.34 2.82.93 4.03l3.02-2.33Z"
311
- fill="var(--bh-social-google-yellow)"
312
- />
313
- <path
314
- d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58C13.47.9 11.43 0 9 0A9 9 0 0 0 .93 4.97L3.95 7.3C4.66 5.17 6.65 3.58 9 3.58Z"
315
- fill="var(--bh-social-google-red)"
316
- />
317
- </>
318
- )
319
- }
320
-
321
- function LinkedInIcon({ color }: { color?: string }) {
322
- return (
323
- <>
324
- <path
325
- d="M3.23 7.2h2.43V15H3.23V7.2Zm1.22-3.88a1.41 1.41 0 1 1 0 2.82 1.41 1.41 0 0 1 0-2.82Z"
326
- fill={color}
327
- />
328
- <path
329
- d="M7.18 7.2h2.33v1.07h.03c.32-.61 1.12-1.26 2.3-1.26 2.47 0 2.93 1.63 2.93 3.74V15h-2.43v-3.77c0-.9-.02-2.06-1.26-2.06-1.26 0-1.45.98-1.45 1.99V15H7.18V7.2Z"
330
- fill={color}
331
- />
332
- </>
333
- )
334
- }
335
-
336
- function TwitterIcon({ color }: { color?: string }) {
337
- return (
338
- <path
339
- d="M10.65 7.72 16.16 1.5h-1.31l-4.78 5.4-3.82-5.4H1.83l5.78 8.17-5.78 6.83h1.31l5.05-5.97 4.04 5.97h4.42l-6-8.78Zm-1.79 2.08-.58-.82-4.66-6.4h1.72l3.76 5.17.58.82 4.89 6.72h-1.72L8.86 9.8Z"
340
- fill={color}
273
+ strokeWidth={platform === "apple" ? 2 : 2.25}
274
+ style={{ color: "var(--bh-social-button-icon)" }}
341
275
  />
342
276
  )
343
277
  }
344
278
 
345
- function WhatsAppIcon({ color }: { color?: string }) {
346
- return (
347
- <path
348
- d="M9.03 1.5A7.42 7.42 0 0 0 2.6 12.62L1.5 16.5l3.98-1.05A7.43 7.43 0 1 0 9.03 1.5Zm0 13.56c-1.22 0-2.35-.36-3.3-.98l-.24-.15-2.36.62.63-2.3-.16-.24a6.1 6.1 0 1 1 5.43 3.05Zm3.34-4.57c-.18-.09-1.08-.53-1.25-.59-.17-.06-.29-.09-.42.09-.12.18-.48.59-.59.71-.11.12-.22.13-.4.04-.18-.09-.77-.28-1.47-.9-.54-.48-.91-1.08-1.02-1.26-.11-.18-.01-.28.08-.37.08-.08.18-.22.27-.33.09-.11.12-.18.18-.3.06-.12.03-.23-.01-.33-.05-.09-.42-1-.57-1.37-.15-.36-.3-.31-.42-.32h-.36c-.12 0-.33.05-.5.23-.17.18-.65.64-.65 1.56 0 .92.67 1.81.76 1.94.09.12 1.32 2.02 3.2 2.83.45.19.8.31 1.07.4.45.14.86.12 1.18.07.36-.05 1.08-.44 1.23-.86.15-.42.15-.79.11-.86-.05-.08-.17-.13-.35-.22Z"
349
- fill={color}
350
- />
351
- )
279
+ const socialButtonIcons: Record<SocialPlatform, LucideIcon> = {
280
+ apple: AppleIcon,
281
+ facebook: FacebookIcon,
282
+ google: ChromeIcon,
283
+ linkedin: LinkedinIcon,
284
+ twitter: TwitterIcon,
285
+ whatsapp: MessageCircleIcon,
352
286
  }
353
287
 
354
288
  export { SocialButton, socialButtonVariants, socialPlatformConfig }