banhaten 0.1.0 → 0.1.1

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 (58) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  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/avatar.tsx +1 -2
  7. package/registry/components/button-group.tsx +1 -1
  8. package/registry/components/card.tsx +1 -1
  9. package/registry/components/checkbox.tsx +19 -16
  10. package/registry/components/expanded/ActivityFeed.tsx +37 -23
  11. package/registry/components/expanded/Banner.tsx +54 -19
  12. package/registry/components/expanded/Breadcrumbs.tsx +10 -38
  13. package/registry/components/expanded/CatalogComponentsShowcase.tsx +11 -16
  14. package/registry/components/expanded/CatalogTag.tsx +4 -11
  15. package/registry/components/expanded/CommandBar.tsx +33 -53
  16. package/registry/components/expanded/FileUpload.tsx +362 -59
  17. package/registry/components/expanded/OnboardingStepListItem.tsx +6 -10
  18. package/registry/components/expanded/PageHeader.tsx +2 -11
  19. package/registry/components/expanded/Slideout.tsx +12 -23
  20. package/registry/components/expanded/Steps.tsx +6 -8
  21. package/registry/components/expanded/Table.tsx +18 -40
  22. package/registry/components/expanded/Timeline.tsx +5 -24
  23. package/registry/components/expanded/activityFeed.css +10 -54
  24. package/registry/components/expanded/banner.css +8 -75
  25. package/registry/components/expanded/breadcrumbs.css +1 -1
  26. package/registry/components/expanded/commandBar.css +23 -26
  27. package/registry/components/expanded/divider.css +1 -1
  28. package/registry/components/expanded/fileUpload.css +304 -75
  29. package/registry/components/expanded/pageHeader.css +1 -1
  30. package/registry/components/expanded/steps.css +15 -51
  31. package/registry/components/expanded/table.css +5 -1
  32. package/registry/components/expanded/timeline.css +18 -15
  33. package/registry/components/input.tsx +125 -54
  34. package/registry/components/menu.tsx +99 -72
  35. package/registry/components/pagination.tsx +6 -18
  36. package/registry/components/radio-card.tsx +25 -31
  37. package/registry/components/select-content.tsx +28 -123
  38. package/registry/components/select.tsx +9 -9
  39. package/registry/components/social-button.tsx +24 -90
  40. package/registry/components/spinner.tsx +21 -5
  41. package/registry/components/textarea.tsx +20 -35
  42. package/registry/components/toggle.tsx +7 -23
  43. package/registry/components/tooltip.tsx +4 -4
  44. package/registry/examples/attribute-demo.tsx +2 -2
  45. package/registry/examples/checkbox-demo.tsx +3 -8
  46. package/registry/examples/date-picker-demo.tsx +75 -22
  47. package/registry/examples/expanded/banner-demo.tsx +31 -6
  48. package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -0
  49. package/registry/examples/expanded/file-upload-demo.tsx +60 -0
  50. package/registry/examples/expanded/steps-demo.tsx +11 -0
  51. package/registry/examples/expanded/table-demo.tsx +142 -0
  52. package/registry/examples/progress-demo.tsx +2 -2
  53. package/registry/examples/select-demo.tsx +32 -18
  54. package/registry/examples/social-button-demo.tsx +33 -33
  55. package/registry/examples/spinner-demo.tsx +37 -0
  56. package/registry/examples/tag-demo.tsx +1 -1
  57. package/registry/index.json +26 -12
  58. package/registry/styles/globals.css +5 -3
@@ -1,5 +1,14 @@
1
1
  import * as React from "react"
2
2
  import { cva, type VariantProps } from "class-variance-authority"
3
+ import {
4
+ AlertCircleIcon,
5
+ ChartNoAxesCombinedIcon,
6
+ CheckIcon,
7
+ ChevronDownIcon,
8
+ InfoIcon,
9
+ PlusIcon,
10
+ UserIcon,
11
+ } from "lucide-react"
3
12
 
4
13
  import { cn } from "@/lib/utils"
5
14
 
@@ -7,7 +16,6 @@ type SelectItemType =
7
16
  | "default"
8
17
  | "icon"
9
18
  | "avatar"
10
- | "flag"
11
19
  | "company"
12
20
  | "payment"
13
21
  | "dot"
@@ -77,40 +85,6 @@ function SelectItemAvatar({
77
85
  )
78
86
  }
79
87
 
80
- type SelectItemFlagProps = React.ComponentProps<"span"> & {
81
- alt?: string
82
- src?: string
83
- }
84
-
85
- function SelectItemFlag({
86
- alt = "",
87
- className,
88
- src,
89
- ...props
90
- }: SelectItemFlagProps) {
91
- return (
92
- <span
93
- data-slot="select-item-flag"
94
- className={cn(
95
- "relative size-[var(--bh-select-icon-slot-size)] shrink-0 overflow-hidden rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-always-white)]",
96
- className
97
- )}
98
- {...props}
99
- >
100
- {src ? (
101
- <img alt={alt} className="size-full object-cover" src={src} />
102
- ) : (
103
- <>
104
- <span className="absolute inset-x-0 top-0 h-1/3 bg-[var(--bh-bg-accent-red-default)]" />
105
- <span className="absolute inset-x-0 top-1/3 h-1/3 bg-[var(--bh-bg-always-white)]" />
106
- <span className="absolute inset-x-0 bottom-0 h-1/3 bg-[var(--bh-bg-always-dark)]" />
107
- <span className="absolute start-1/2 top-1/2 size-[var(--bh-space-xs-4)] -translate-x-1/2 -translate-y-1/2 rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-accent-golden-default)]" />
108
- </>
109
- )}
110
- </span>
111
- )
112
- }
113
-
114
88
  type SelectItemCompanyLogoProps = React.ComponentProps<"span">
115
89
 
116
90
  function SelectItemCompanyLogo({
@@ -126,27 +100,12 @@ function SelectItemCompanyLogo({
126
100
  )}
127
101
  {...props}
128
102
  >
129
- <svg
103
+ <ChartNoAxesCombinedIcon
130
104
  aria-hidden="true"
131
105
  className="size-[var(--bh-select-company-icon-size)]"
132
- fill="none"
133
106
  focusable="false"
134
- viewBox="0 0 18 18"
135
- >
136
- <path
137
- d="M3 10.25C5.4 6.75 7.5 6.75 10 9.4C11.6 11.1 13 11 15 8.75"
138
- stroke="currentColor"
139
- strokeLinecap="round"
140
- strokeWidth="2.4"
141
- />
142
- <path
143
- d="M3 7.7C5.3 4.5 7.4 4.5 9.8 7.05C11.4 8.75 13 8.65 15 6.4"
144
- stroke="currentColor"
145
- strokeLinecap="round"
146
- strokeWidth="2.4"
147
- opacity="var(--bh-opacity-70)"
148
- />
149
- </svg>
107
+ strokeWidth={2.2}
108
+ />
150
109
  </span>
151
110
  )
152
111
  }
@@ -198,7 +157,6 @@ const defaultSelectItemMedia: Partial<Record<SelectItemType, () => React.ReactNo
198
157
  avatar: () => <SelectItemAvatar />,
199
158
  company: () => <SelectItemCompanyLogo />,
200
159
  dot: () => <SelectItemStatusDot />,
201
- flag: () => <SelectItemFlag />,
202
160
  icon: () => <SelectIcon name="plus" />,
203
161
  payment: () => <SelectItemPaymentIcon />,
204
162
  }
@@ -215,87 +173,35 @@ function SelectIcon({
215
173
  name: SelectIconName
216
174
  }) {
217
175
  const iconClassName = cn("size-[var(--bh-select-icon-size)]", className)
176
+ const iconProps = {
177
+ "aria-hidden": true,
178
+ className: iconClassName,
179
+ focusable: false,
180
+ strokeWidth: 2,
181
+ } as const
218
182
 
219
183
  if (name === "user") {
220
- return (
221
- <svg
222
- aria-hidden="true"
223
- className={iconClassName}
224
- fill="none"
225
- focusable="false"
226
- viewBox="0 0 16 16"
227
- >
228
- <path
229
- d="M8 8C5.79 8 4 6.21 4 4S5.79 0 8 0s4 1.79 4 4s-1.79 4-4 4Zm0 1.5c3.31 0 6 1.79 6 4v1H2v-1c0-2.21 2.69-4 6-4Zm0-3A2.5 2.5 0 1 0 8 1a2.5 2.5 0 0 0 0 5.5Zm-4.36 7h8.72C11.8 12.08 10.05 11 8 11s-3.8 1.08-4.36 2.5Z"
230
- fill="currentColor"
231
- />
232
- </svg>
233
- )
184
+ return <UserIcon {...iconProps} />
234
185
  }
235
186
 
236
- if (name === "info" || name === "error") {
237
- return (
238
- <svg
239
- aria-hidden="true"
240
- className={iconClassName}
241
- fill="none"
242
- focusable="false"
243
- viewBox="0 0 16 16"
244
- >
245
- <path
246
- d="M8 14.667A6.667 6.667 0 1 1 8 1.333a6.667 6.667 0 0 1 0 13.334ZM7.333 9.333v1.334h1.334V9.333H7.333Zm0-4v2.834h1.334V5.333H7.333Z"
247
- fill="currentColor"
248
- />
249
- </svg>
250
- )
187
+ if (name === "info") {
188
+ return <InfoIcon {...iconProps} />
189
+ }
190
+
191
+ if (name === "error") {
192
+ return <AlertCircleIcon {...iconProps} />
251
193
  }
252
194
 
253
195
  if (name === "chevron-down") {
254
- return (
255
- <svg
256
- aria-hidden="true"
257
- className={iconClassName}
258
- fill="none"
259
- focusable="false"
260
- viewBox="0 0 16 16"
261
- >
262
- <path
263
- d="M8 10.667 3.333 6l.934-.933L8 8.8l3.733-3.733.934.933L8 10.667Z"
264
- fill="currentColor"
265
- />
266
- </svg>
267
- )
196
+ return <ChevronDownIcon {...iconProps} />
268
197
  }
269
198
 
270
199
  if (name === "plus") {
271
- return (
272
- <svg
273
- aria-hidden="true"
274
- className={iconClassName}
275
- fill="none"
276
- focusable="false"
277
- viewBox="0 0 20 20"
278
- >
279
- <path d="M9.167 9.167V4.5h1.666v4.667H15.5v1.666h-4.667V15.5H9.167v-4.667H4.5V9.167h4.667Z" fill="currentColor" />
280
- </svg>
281
- )
200
+ return <PlusIcon {...iconProps} />
282
201
  }
283
202
 
284
203
  if (name === "check-fill" || name === "check-line") {
285
- return (
286
- <svg
287
- aria-hidden="true"
288
- className={iconClassName}
289
- fill="none"
290
- focusable="false"
291
- viewBox="0 0 20 20"
292
- >
293
- <path
294
- d="m8.333 12.643 7.66-7.66 1.179 1.178-8.839 8.839-5.303-5.303 1.178-1.179 4.125 4.125Z"
295
- fill="currentColor"
296
- />
297
- </svg>
298
- )
204
+ return <CheckIcon {...iconProps} />
299
205
  }
300
206
 
301
207
  return null
@@ -306,7 +212,6 @@ export {
306
212
  SelectIcon,
307
213
  SelectItemAvatar,
308
214
  SelectItemCompanyLogo,
309
- SelectItemFlag,
310
215
  SelectItemPaymentIcon,
311
216
  SelectItemStatusDot,
312
217
  }
@@ -10,7 +10,6 @@ import {
10
10
  SelectIcon,
11
11
  SelectItemAvatar,
12
12
  SelectItemCompanyLogo,
13
- SelectItemFlag,
14
13
  SelectItemPaymentIcon,
15
14
  SelectItemStatusDot,
16
15
  type SelectItemType,
@@ -29,10 +28,12 @@ const selectRoot = cva(
29
28
  const selectTrigger = cva(
30
29
  [
31
30
  "group/select-trigger relative flex w-full items-center gap-[var(--bh-select-trigger-gap)] rounded-[var(--bh-select-trigger-radius)]",
32
- "px-[var(--bh-select-trigger-padding-x)] text-start outline-none",
31
+ "select-none px-[var(--bh-select-trigger-padding-x)] text-start outline-none",
33
32
  "transition-[background-color,box-shadow]",
34
33
  "[--bh-select-trigger-border-current:var(--bh-select-trigger-border)] [--shadow-select-trigger:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-trigger-border-current,var(--bh-select-trigger-border)),var(--shadow-component-default)]",
35
- "focus-visible:shadow-[var(--shadow-select-focus-ring)]",
34
+ "[--bh-select-focus-ring-color:color-mix(in_srgb,var(--bh-border-focus)_30%,transparent)] [--shadow-select-focus-border:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-trigger-border-current,var(--bh-select-trigger-border))]",
35
+ "after:pointer-events-none after:absolute after:inset-[calc(var(--bh-focus-ring-width)*-1)] after:rounded-[calc(var(--bh-select-trigger-radius)+var(--bh-focus-ring-width))] after:border-[length:var(--bh-focus-ring-width)] after:border-solid after:border-transparent after:content-['']",
36
+ "focus-visible:[--bh-select-trigger-border-current:var(--bh-select-trigger-border-focus)] focus-visible:[box-shadow:var(--shadow-select-focus-border)] focus-visible:after:border-[var(--bh-select-focus-ring-color)]",
36
37
  "aria-invalid:[--bh-select-trigger-border-current:var(--bh-select-trigger-border-error)]",
37
38
  "disabled:pointer-events-none disabled:bg-[var(--bh-select-trigger-bg-disabled)] disabled:shadow-[inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-trigger-border-disabled)]",
38
39
  "[&_svg]:pointer-events-none [&_svg]:shrink-0",
@@ -53,7 +54,7 @@ const selectTrigger = cva(
53
54
  default: "",
54
55
  filled: "",
55
56
  error:
56
- "[--bh-select-trigger-border-current:var(--bh-select-trigger-border-error)] shadow-[var(--shadow-select-trigger)] focus-visible:shadow-[var(--shadow-select-danger-focus-ring)]",
57
+ "[--bh-select-trigger-border-current:var(--bh-select-trigger-border-error)] [--bh-select-focus-ring-color:color-mix(in_srgb,var(--bh-border-focus-danger)_30%,transparent)] shadow-[var(--shadow-select-trigger)] focus-visible:[box-shadow:var(--shadow-select-focus-border)]",
57
58
  disabled:
58
59
  "pointer-events-none bg-[var(--bh-select-trigger-bg-disabled)] shadow-[inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-trigger-border-disabled)]",
59
60
  },
@@ -69,7 +70,7 @@ const selectTrigger = cva(
69
70
  const selectMenu = cva(
70
71
  [
71
72
  "w-[var(--radix-popper-anchor-width,var(--bh-select-menu-width))] max-w-[var(--radix-popper-available-width,100vw)] overflow-hidden rounded-[var(--bh-select-menu-radius)]",
72
- "bg-[var(--bh-select-menu-bg)] py-[var(--bh-select-menu-padding-y)]",
73
+ "select-none bg-[var(--bh-select-menu-bg)] py-[var(--bh-select-menu-padding-y)]",
73
74
  "shadow-[var(--shadow-select-menu)]",
74
75
  ].join(" ")
75
76
  )
@@ -81,7 +82,7 @@ const selectMenuList = cva(
81
82
  const selectMenuItem = cva(
82
83
  [
83
84
  "group/select-menu-item relative flex min-h-[var(--bh-select-item-min-height)] w-full items-center bg-transparent",
84
- "px-[var(--bh-select-item-padding-x)] text-start outline-none",
85
+ "select-none px-[var(--bh-select-item-padding-x)] text-start outline-none",
85
86
  "disabled:pointer-events-none data-[disabled=true]:pointer-events-none",
86
87
  "focus-visible:[&>[data-slot=select-menu-item-content]]:bg-[var(--bh-select-item-hover-bg)]",
87
88
  ],
@@ -821,7 +822,7 @@ function SelectCheckboxIndicator({
821
822
  <span
822
823
  data-slot="select-checkbox-control"
823
824
  className={cn(
824
- "pointer-events-none absolute start-1/2 top-1/2 size-[var(--bh-select-checkbox-size)] -translate-x-1/2 -translate-y-1/2 rounded-[var(--bh-select-checkbox-radius)] shadow-[var(--shadow-select-checkbox)] [--bh-select-checkbox-border:var(--bh-border-input)] [--shadow-select-checkbox:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-checkbox-border,var(--bh-border-input)),var(--shadow-component-default)]",
825
+ "pointer-events-none absolute left-1/2 top-1/2 size-[var(--bh-select-checkbox-size)] -translate-x-1/2 -translate-y-1/2 rounded-[var(--bh-select-checkbox-radius)] shadow-[var(--shadow-select-checkbox)] [--bh-select-checkbox-border:var(--bh-border-input)] [--shadow-select-checkbox:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-select-checkbox-border,var(--bh-border-input)),var(--shadow-component-default)]",
825
826
  checked
826
827
  ? "bg-[var(--bh-interactive-checkbox-default)] [--bh-select-checkbox-border:transparent]"
827
828
  : "bg-[var(--bh-bg-default)]",
@@ -830,7 +831,7 @@ function SelectCheckboxIndicator({
830
831
  )}
831
832
  />
832
833
  {checked ? (
833
- <span className="absolute start-1/2 top-1/2 flex size-[var(--bh-select-checkbox-icon-size)] -translate-x-1/2 -translate-y-1/2 items-center justify-center text-[var(--bh-content-on-color)]">
834
+ <span className="absolute left-1/2 top-1/2 flex size-[var(--bh-select-checkbox-icon-size)] -translate-x-1/2 -translate-y-1/2 items-center justify-center text-[var(--bh-content-on-color)]">
834
835
  <SelectIcon name="check-fill" />
835
836
  </span>
836
837
  ) : null}
@@ -844,7 +845,6 @@ export {
844
845
  SelectHelperText,
845
846
  SelectItemAvatar,
846
847
  SelectItemCompanyLogo,
847
- SelectItemFlag,
848
848
  SelectItemPaymentIcon,
849
849
  SelectItemStatusDot,
850
850
  SelectLabel,
@@ -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 }
@@ -8,7 +8,7 @@ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
8
8
  aria-hidden="true"
9
9
  data-slot="spinner"
10
10
  viewBox="0 0 24 24"
11
- className={cn("size-[var(--bh-spinner-size)] animate-spin text-current", className)}
11
+ className={cn("size-[var(--bh-spinner-size)] shrink-0 text-current", className)}
12
12
  {...props}
13
13
  >
14
14
  <circle
@@ -20,10 +20,26 @@ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
20
20
  strokeWidth="4"
21
21
  opacity="var(--bh-opacity-25)"
22
22
  />
23
- <path
24
- fill="currentColor"
25
- d="M22 12a10 10 0 0 1-10 10v-4a6 6 0 0 0 6-6z"
26
- />
23
+ <circle
24
+ cx="12"
25
+ cy="12"
26
+ r="10"
27
+ fill="none"
28
+ stroke="currentColor"
29
+ strokeWidth="4"
30
+ strokeLinecap="round"
31
+ pathLength="100"
32
+ strokeDasharray="30 70"
33
+ >
34
+ <animateTransform
35
+ attributeName="transform"
36
+ dur="1s"
37
+ from="0 12 12"
38
+ repeatCount="indefinite"
39
+ to="360 12 12"
40
+ type="rotate"
41
+ />
42
+ </circle>
27
43
  </svg>
28
44
  )
29
45
  }
@@ -1,5 +1,6 @@
1
1
  import * as React from "react"
2
2
  import { cva } from "class-variance-authority"
3
+ import { CircleAlertIcon, InfoIcon, XIcon } from "lucide-react"
3
4
 
4
5
  import { cn } from "@/lib/utils"
5
6
 
@@ -533,53 +534,37 @@ function TextareaIcon({
533
534
  className
534
535
  )}
535
536
  >
536
- <svg
537
- className="size-[var(--bh-textarea-helper-icon-size)]"
538
- fill="none"
539
- focusable="false"
540
- viewBox="0 0 13.3333 13.3333"
541
- >
542
- {type === "error" ? <ErrorIconPath /> : <InfoIconPath />}
543
- </svg>
537
+ {type === "error" ? (
538
+ <CircleAlertIcon
539
+ aria-hidden="true"
540
+ className="size-[var(--bh-textarea-helper-icon-size)]"
541
+ focusable="false"
542
+ strokeWidth={2.25}
543
+ />
544
+ ) : (
545
+ <InfoIcon
546
+ aria-hidden="true"
547
+ className="size-[var(--bh-textarea-helper-icon-size)]"
548
+ focusable="false"
549
+ strokeWidth={2.25}
550
+ />
551
+ )}
544
552
  </span>
545
553
  )
546
554
  }
547
555
 
548
- function ErrorIconPath() {
549
- return (
550
- <path
551
- d="M6.66667 13.3333C2.98477 13.3333 0 10.3485 0 6.66667C0 2.98477 2.98477 0 6.66667 0C10.3485 0 13.3333 2.98477 13.3333 6.66667C13.3333 10.3485 10.3485 13.3333 6.66667 13.3333ZM6 8.66667V10H7.33333V8.66667H6ZM6 3.33333V7.33333H7.33333V3.33333H6Z"
552
- fill="currentColor"
553
- />
554
- )
555
- }
556
-
557
- function InfoIconPath() {
558
- return (
559
- <path
560
- d="M6.66667 13.3333C2.98477 13.3333 0 10.3485 0 6.66667C0 2.98477 2.98477 0 6.66667 0C10.3485 0 13.3333 2.98477 13.3333 6.66667C13.3333 10.3485 10.3485 13.3333 6.66667 13.3333ZM6.66667 5C7.21893 5 7.66667 4.55229 7.66667 4C7.66667 3.44771 7.21893 3 6.66667 3C6.1144 3 5.66667 3.44771 5.66667 4C5.66667 4.55229 6.1144 5 6.66667 5ZM8 8.66667H7.33333V5.66667H5.33333V7H6V8.66667H5.33333V10H8V8.66667Z"
561
- fill="currentColor"
562
- />
563
- )
564
- }
565
-
566
556
  function CloseIcon() {
567
557
  return (
568
558
  <span
569
559
  aria-hidden="true"
570
560
  className="flex size-[var(--bh-textarea-close-button-size)] items-center justify-center"
571
561
  >
572
- <svg
562
+ <XIcon
563
+ aria-hidden="true"
573
564
  className="size-[var(--bh-textarea-close-icon-size)]"
574
- fill="none"
575
565
  focusable="false"
576
- viewBox="0 0 6.36398 6.36394"
577
- >
578
- <path
579
- d="M3.18198 2.47489L5.65688 0L6.36398 0.707105L3.88908 3.18199L6.36398 5.65684L5.65688 6.36394L3.18198 3.88909L0.70711 6.36394L0 5.65684L2.47488 3.18199L0 0.707105L0.70711 0L3.18198 2.47489Z"
580
- fill="currentColor"
581
- />
582
- </svg>
566
+ strokeWidth={2.5}
567
+ />
583
568
  </span>
584
569
  )
585
570
  }
@@ -3,6 +3,7 @@
3
3
  import * as React from "react"
4
4
  import * as SwitchPrimitive from "@radix-ui/react-switch"
5
5
  import { cva, type VariantProps } from "class-variance-authority"
6
+ import { CheckIcon, XIcon } from "lucide-react"
6
7
 
7
8
  import { cn } from "@/lib/utils"
8
9
 
@@ -226,40 +227,23 @@ const ToggleField = React.forwardRef<HTMLDivElement, ToggleFieldProps>(
226
227
 
227
228
  function ToggleCheckIcon({ className }: { className?: string }) {
228
229
  return (
229
- <svg
230
+ <CheckIcon
230
231
  aria-hidden="true"
231
232
  className={className}
232
- fill="none"
233
233
  focusable="false"
234
- viewBox="0 0 16 16"
235
- >
236
- <path
237
- d="M4 8.2 6.55 10.75 12 5.25"
238
- stroke="currentColor"
239
- strokeLinecap="round"
240
- strokeLinejoin="round"
241
- strokeWidth="1.75"
242
- />
243
- </svg>
234
+ strokeWidth={2.5}
235
+ />
244
236
  )
245
237
  }
246
238
 
247
239
  function ToggleCloseIcon({ className }: { className?: string }) {
248
240
  return (
249
- <svg
241
+ <XIcon
250
242
  aria-hidden="true"
251
243
  className={className}
252
- fill="none"
253
244
  focusable="false"
254
- viewBox="0 0 16 16"
255
- >
256
- <path
257
- d="m5 5 6 6m0-6-6 6"
258
- stroke="currentColor"
259
- strokeLinecap="round"
260
- strokeWidth="1.75"
261
- />
262
- </svg>
245
+ strokeWidth={2.5}
246
+ />
263
247
  )
264
248
  }
265
249
 
@@ -386,13 +386,13 @@ const pointerPlacement: Record<Exclude<TooltipPointerPosition, "none">, string>
386
386
 
387
387
  const pointerFillShape = {
388
388
  top:
389
- "left-0 top-0 border-x-[length:var(--bh-tooltip-pointer-half-width)] border-b-[length:var(--bh-tooltip-pointer-depth)] border-x-[color:transparent] border-b-[color:var(--bh-tooltip-bg)]",
389
+ "left-0 top-[var(--bh-space-xxxs-1)] border-x-[length:var(--bh-tooltip-pointer-half-width)] border-b-[length:var(--bh-tooltip-pointer-depth)] border-x-[color:transparent] border-b-[color:var(--bh-tooltip-bg)]",
390
390
  bottom:
391
- "bottom-0 left-0 border-x-[length:var(--bh-tooltip-pointer-half-width)] border-t-[length:var(--bh-tooltip-pointer-depth)] border-x-[color:transparent] border-t-[color:var(--bh-tooltip-bg)]",
391
+ "bottom-[var(--bh-space-xxxs-1)] left-0 border-x-[length:var(--bh-tooltip-pointer-half-width)] border-t-[length:var(--bh-tooltip-pointer-depth)] border-x-[color:transparent] border-t-[color:var(--bh-tooltip-bg)]",
392
392
  right:
393
- "left-0 top-0 border-y-[length:var(--bh-tooltip-pointer-half-width)] border-l-[length:var(--bh-tooltip-pointer-depth)] border-y-[color:transparent] border-l-[color:var(--bh-tooltip-bg)]",
393
+ "left-[calc(var(--bh-space-xxxs-1)*-1)] top-0 border-y-[length:var(--bh-tooltip-pointer-half-width)] border-l-[length:var(--bh-tooltip-pointer-depth)] border-y-[color:transparent] border-l-[color:var(--bh-tooltip-bg)]",
394
394
  left:
395
- "right-0 top-0 border-y-[length:var(--bh-tooltip-pointer-half-width)] border-r-[length:var(--bh-tooltip-pointer-depth)] border-y-[color:transparent] border-r-[color:var(--bh-tooltip-bg)]",
395
+ "right-[calc(var(--bh-space-xxxs-1)*-1)] top-0 border-y-[length:var(--bh-tooltip-pointer-half-width)] border-r-[length:var(--bh-tooltip-pointer-depth)] border-y-[color:transparent] border-r-[color:var(--bh-tooltip-bg)]",
396
396
  } as const
397
397
 
398
398
  const pointerBorderShape = {
@@ -38,9 +38,9 @@ export function AttributeDemo() {
38
38
  <AttributeCard>
39
39
  <AttributeHeader
40
40
  title="Order details"
41
- description="End-aligned values, copy actions, files, and status chips."
41
+ description="Rich values with copy actions, files, and status chips."
42
42
  />
43
- <AttributeList layout="end" dividers>
43
+ <AttributeList dividers>
44
44
  <AttributeItem label="Subscription">
45
45
  <Badge color="green" type="dot">
46
46
  Active