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.
- package/README.md +21 -9
- package/package.json +8 -2
- package/registry/components/accordion.tsx +37 -1
- package/registry/components/alert.tsx +14 -28
- package/registry/components/attribute.tsx +6 -10
- package/registry/components/autocomplete.tsx +637 -0
- package/registry/components/avatar.tsx +259 -24
- package/registry/components/badge.tsx +97 -35
- package/registry/components/button-group.tsx +1 -1
- package/registry/components/card.tsx +1 -1
- package/registry/components/checkbox.tsx +19 -16
- package/registry/components/date-picker-state.ts +253 -0
- package/registry/components/date-picker.tsx +115 -158
- package/registry/components/expanded/ActivityFeed.tsx +37 -23
- package/registry/components/expanded/Banner.tsx +54 -19
- package/registry/components/expanded/Breadcrumbs.tsx +10 -38
- package/registry/components/expanded/CatalogComponentsShowcase.tsx +11 -16
- package/registry/components/expanded/CatalogTag.tsx +4 -11
- package/registry/components/expanded/CommandBar.tsx +33 -53
- package/registry/components/expanded/EmptyState.tsx +155 -0
- package/registry/components/expanded/FileUpload.tsx +362 -59
- package/registry/components/expanded/OnboardingStepListItem.tsx +6 -10
- package/registry/components/expanded/PageHeader.tsx +2 -11
- package/registry/components/expanded/Slideout.tsx +12 -23
- package/registry/components/expanded/Steps.tsx +6 -8
- package/registry/components/expanded/Table.tsx +18 -40
- package/registry/components/expanded/Timeline.tsx +5 -24
- package/registry/components/expanded/activityFeed.css +10 -54
- package/registry/components/expanded/banner.css +8 -75
- package/registry/components/expanded/breadcrumbs.css +1 -1
- package/registry/components/expanded/commandBar.css +23 -26
- package/registry/components/expanded/divider.css +1 -1
- package/registry/components/expanded/emptyState.css +111 -0
- package/registry/components/expanded/fileUpload.css +304 -75
- package/registry/components/expanded/pageHeader.css +1 -1
- package/registry/components/expanded/slideout.css +1 -0
- package/registry/components/expanded/steps.css +15 -51
- package/registry/components/expanded/table.css +6 -1
- package/registry/components/expanded/timeline.css +18 -15
- package/registry/components/input-otp.tsx +574 -0
- package/registry/components/input.tsx +140 -59
- package/registry/components/menu.tsx +470 -80
- package/registry/components/pagination.tsx +6 -18
- package/registry/components/popover.tsx +840 -0
- package/registry/components/radio-card.tsx +25 -31
- package/registry/components/select-content.tsx +28 -123
- package/registry/components/select.tsx +13 -9
- package/registry/components/skeleton.css +57 -0
- package/registry/components/skeleton.tsx +482 -0
- package/registry/components/social-button.tsx +24 -90
- package/registry/components/spinner.tsx +91 -7
- package/registry/components/textarea.tsx +21 -36
- package/registry/components/toggle.tsx +7 -23
- package/registry/components/tooltip.tsx +8 -4
- package/registry/examples/attribute-demo.tsx +2 -2
- package/registry/examples/autocomplete-demo.tsx +109 -0
- package/registry/examples/avatar-demo.tsx +102 -47
- package/registry/examples/badge-demo.tsx +16 -0
- package/registry/examples/checkbox-demo.tsx +3 -8
- package/registry/examples/date-picker-demo.tsx +75 -22
- package/registry/examples/expanded/banner-demo.tsx +31 -6
- package/registry/examples/expanded/breadcrumbs-demo.tsx +59 -0
- package/registry/examples/expanded/command-bar-demo.tsx +236 -0
- package/registry/examples/expanded/empty-state-demo.tsx +39 -0
- package/registry/examples/expanded/file-upload-demo.tsx +60 -0
- package/registry/examples/expanded/steps-demo.tsx +11 -0
- package/registry/examples/expanded/table-demo.tsx +142 -0
- package/registry/examples/input-demo.tsx +1 -1
- package/registry/examples/input-otp-demo.tsx +72 -0
- package/registry/examples/menu-demo.tsx +101 -88
- package/registry/examples/popover-demo.tsx +546 -0
- package/registry/examples/progress-demo.tsx +2 -2
- package/registry/examples/select-demo.tsx +32 -18
- package/registry/examples/skeleton-demo.tsx +56 -0
- package/registry/examples/social-button-demo.tsx +33 -33
- package/registry/examples/spinner-demo.tsx +59 -0
- package/registry/examples/tag-demo.tsx +1 -1
- package/registry/examples/textarea-demo.tsx +1 -1
- package/registry/index.json +266 -20
- package/registry/styles/globals.css +93 -3
- package/src/cli/index.js +997 -62
|
@@ -2,16 +2,39 @@ import * as React from "react"
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type SpinnerMotion = "dynamic" | "steady"
|
|
6
|
+
|
|
7
|
+
type SpinnerProps = React.ComponentProps<"svg">
|
|
8
|
+
|
|
9
|
+
type DynamicSpinnerProps = SpinnerProps
|
|
10
|
+
|
|
11
|
+
type SpinnerBaseProps = SpinnerProps & {
|
|
12
|
+
motion: SpinnerMotion
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Spinner(props: SpinnerProps) {
|
|
16
|
+
return <SpinnerBase {...props} motion="steady" />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DynamicSpinner(props: DynamicSpinnerProps) {
|
|
20
|
+
return <SpinnerBase {...props} motion="dynamic" />
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function SpinnerBase({ className, motion, ...props }: SpinnerBaseProps) {
|
|
6
24
|
return (
|
|
7
25
|
<svg
|
|
8
26
|
aria-hidden="true"
|
|
27
|
+
data-motion={motion}
|
|
9
28
|
data-slot="spinner"
|
|
10
29
|
viewBox="0 0 24 24"
|
|
11
|
-
className={cn(
|
|
30
|
+
className={cn(
|
|
31
|
+
"size-[var(--bh-spinner-size)] shrink-0 text-current",
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
12
34
|
{...props}
|
|
13
35
|
>
|
|
14
36
|
<circle
|
|
37
|
+
data-slot="spinner-track"
|
|
15
38
|
cx="12"
|
|
16
39
|
cy="12"
|
|
17
40
|
r="10"
|
|
@@ -20,12 +43,73 @@ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
|
|
|
20
43
|
strokeWidth="4"
|
|
21
44
|
opacity="var(--bh-opacity-25)"
|
|
22
45
|
/>
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
46
|
+
<circle
|
|
47
|
+
data-slot="spinner-arc"
|
|
48
|
+
cx="12"
|
|
49
|
+
cy="12"
|
|
50
|
+
r="10"
|
|
51
|
+
fill="none"
|
|
52
|
+
stroke="currentColor"
|
|
53
|
+
strokeWidth="4"
|
|
54
|
+
strokeLinecap="round"
|
|
55
|
+
pathLength="100"
|
|
56
|
+
strokeDasharray="30 70"
|
|
57
|
+
>
|
|
58
|
+
{motion === "dynamic" ? (
|
|
59
|
+
<DynamicSpinnerMotion />
|
|
60
|
+
) : (
|
|
61
|
+
<SteadySpinnerMotion />
|
|
62
|
+
)}
|
|
63
|
+
</circle>
|
|
27
64
|
</svg>
|
|
28
65
|
)
|
|
29
66
|
}
|
|
30
67
|
|
|
31
|
-
|
|
68
|
+
function DynamicSpinnerMotion() {
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<animate
|
|
72
|
+
attributeName="stroke-dasharray"
|
|
73
|
+
calcMode="spline"
|
|
74
|
+
dur="6s"
|
|
75
|
+
keySplines="0.45 0 0.55 1; 0.45 0 0.55 1; 0.45 0 0.55 1; 0.45 0 0.55 1"
|
|
76
|
+
keyTimes="0; 0.25; 0.5; 0.75; 1"
|
|
77
|
+
repeatCount="indefinite"
|
|
78
|
+
values="22 78; 38 62; 30 70; 42 58; 22 78"
|
|
79
|
+
/>
|
|
80
|
+
<animate
|
|
81
|
+
attributeName="stroke-dashoffset"
|
|
82
|
+
calcMode="spline"
|
|
83
|
+
dur="6s"
|
|
84
|
+
keySplines="0.45 0 0.55 1; 0.45 0 0.55 1; 0.45 0 0.55 1; 0.45 0 0.55 1"
|
|
85
|
+
keyTimes="0; 0.25; 0.5; 0.75; 1"
|
|
86
|
+
repeatCount="indefinite"
|
|
87
|
+
values="0; -16; -44; -72; -100"
|
|
88
|
+
/>
|
|
89
|
+
<animateTransform
|
|
90
|
+
attributeName="transform"
|
|
91
|
+
dur="6s"
|
|
92
|
+
from="0 12 12"
|
|
93
|
+
repeatCount="indefinite"
|
|
94
|
+
to="1080 12 12"
|
|
95
|
+
type="rotate"
|
|
96
|
+
/>
|
|
97
|
+
</>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function SteadySpinnerMotion() {
|
|
102
|
+
return (
|
|
103
|
+
<animateTransform
|
|
104
|
+
attributeName="transform"
|
|
105
|
+
dur="1.5s"
|
|
106
|
+
from="0 12 12"
|
|
107
|
+
repeatCount="indefinite"
|
|
108
|
+
to="360 12 12"
|
|
109
|
+
type="rotate"
|
|
110
|
+
/>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { DynamicSpinner, Spinner }
|
|
115
|
+
export type { DynamicSpinnerProps, SpinnerProps }
|
|
@@ -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
|
|
|
@@ -99,7 +100,7 @@ const textareaControl = cva(
|
|
|
99
100
|
variants: {
|
|
100
101
|
type: {
|
|
101
102
|
default:
|
|
102
|
-
"min-h-[calc(var(--bh-textarea-min-height)_-_var(--bh-textarea-padding)_-_var(--bh-textarea-padding))]",
|
|
103
|
+
"min-h-[calc(var(--bh-textarea-min-height)_-_var(--bh-textarea-padding)_-_var(--bh-textarea-padding))] overflow-y-auto [scrollbar-gutter:stable]",
|
|
103
104
|
tags:
|
|
104
105
|
"h-[var(--bh-text-body-md-regular-line-height)] min-h-[var(--bh-text-body-md-regular-line-height)] overflow-hidden",
|
|
105
106
|
},
|
|
@@ -533,53 +534,37 @@ function TextareaIcon({
|
|
|
533
534
|
className
|
|
534
535
|
)}
|
|
535
536
|
>
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
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
|
-
<
|
|
562
|
+
<XIcon
|
|
563
|
+
aria-hidden="true"
|
|
573
564
|
className="size-[var(--bh-textarea-close-icon-size)]"
|
|
574
|
-
fill="none"
|
|
575
565
|
focusable="false"
|
|
576
|
-
|
|
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
|
-
<
|
|
230
|
+
<CheckIcon
|
|
230
231
|
aria-hidden="true"
|
|
231
232
|
className={className}
|
|
232
|
-
fill="none"
|
|
233
233
|
focusable="false"
|
|
234
|
-
|
|
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
|
-
<
|
|
241
|
+
<XIcon
|
|
250
242
|
aria-hidden="true"
|
|
251
243
|
className={className}
|
|
252
|
-
fill="none"
|
|
253
244
|
focusable="false"
|
|
254
|
-
|
|
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
|
|
|
@@ -24,6 +24,8 @@ const defaultTooltipSupportText =
|
|
|
24
24
|
// Radix sideOffset requires numbers; these mirror the tooltip spacing aliases.
|
|
25
25
|
const TOOLTIP_POINTER_SIDE_OFFSET_PX = 7
|
|
26
26
|
const TOOLTIP_POINTERLESS_SIDE_OFFSET_PX = 6
|
|
27
|
+
// Radix collisionPadding requires a number; this mirrors --bh-space-md-8.
|
|
28
|
+
const TOOLTIP_COLLISION_PADDING_PX = 8
|
|
27
29
|
|
|
28
30
|
const tooltipContentVariants = cva(
|
|
29
31
|
[
|
|
@@ -87,6 +89,7 @@ const TooltipContent = React.forwardRef<
|
|
|
87
89
|
children,
|
|
88
90
|
className,
|
|
89
91
|
closeLabel,
|
|
92
|
+
collisionPadding = TOOLTIP_COLLISION_PADDING_PX,
|
|
90
93
|
onCloseClick,
|
|
91
94
|
pointerPosition = "top-left",
|
|
92
95
|
shortcut,
|
|
@@ -127,6 +130,7 @@ const TooltipContent = React.forwardRef<
|
|
|
127
130
|
ref={ref}
|
|
128
131
|
side={side ?? placement.side}
|
|
129
132
|
align={align ?? placement.align}
|
|
133
|
+
collisionPadding={collisionPadding}
|
|
130
134
|
sideOffset={
|
|
131
135
|
sideOffset ??
|
|
132
136
|
(shouldShowPointer
|
|
@@ -386,13 +390,13 @@ const pointerPlacement: Record<Exclude<TooltipPointerPosition, "none">, string>
|
|
|
386
390
|
|
|
387
391
|
const pointerFillShape = {
|
|
388
392
|
top:
|
|
389
|
-
"left-0 top-
|
|
393
|
+
"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
394
|
bottom:
|
|
391
|
-
"bottom-
|
|
395
|
+
"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
396
|
right:
|
|
393
|
-
"left-
|
|
397
|
+
"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
398
|
left:
|
|
395
|
-
"right-
|
|
399
|
+
"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
400
|
} as const
|
|
397
401
|
|
|
398
402
|
const pointerBorderShape = {
|
|
@@ -38,9 +38,9 @@ export function AttributeDemo() {
|
|
|
38
38
|
<AttributeCard>
|
|
39
39
|
<AttributeHeader
|
|
40
40
|
title="Order details"
|
|
41
|
-
description="
|
|
41
|
+
description="Rich values with copy actions, files, and status chips."
|
|
42
42
|
/>
|
|
43
|
-
<AttributeList
|
|
43
|
+
<AttributeList dividers>
|
|
44
44
|
<AttributeItem label="Subscription">
|
|
45
45
|
<Badge color="green" type="dot">
|
|
46
46
|
Active
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Autocomplete } from "@/components/ui/autocomplete"
|
|
2
|
+
|
|
3
|
+
const peopleOptions = [
|
|
4
|
+
{
|
|
5
|
+
value: "ahmed",
|
|
6
|
+
label: "Ahmed Galal",
|
|
7
|
+
addonText: "Design system",
|
|
8
|
+
itemType: "avatar" as const,
|
|
9
|
+
keywords: ["foundations", "tokens"],
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
value: "nora",
|
|
13
|
+
label: "Nora Ali",
|
|
14
|
+
addonText: "Product",
|
|
15
|
+
itemType: "avatar" as const,
|
|
16
|
+
keywords: ["roadmap", "research"],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
value: "layla",
|
|
20
|
+
label: "Layla Hassan",
|
|
21
|
+
addonText: "Engineering",
|
|
22
|
+
itemType: "avatar" as const,
|
|
23
|
+
keywords: ["frontend", "platform"],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: "omar",
|
|
27
|
+
label: "Omar Saleh",
|
|
28
|
+
addonText: "Unavailable",
|
|
29
|
+
itemType: "avatar" as const,
|
|
30
|
+
disabled: true,
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const projectOptions = [
|
|
35
|
+
{ value: "tokens", label: "Token audit", addonText: "In review", itemType: "dot" as const },
|
|
36
|
+
{ value: "inputs", label: "Input system", addonText: "Ready", itemType: "dot" as const },
|
|
37
|
+
{ value: "tables", label: "Table promotion", addonText: "Planned", itemType: "dot" as const },
|
|
38
|
+
{ value: "forms", label: "Form patterns", addonText: "Discovery", itemType: "dot" as const },
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
const rtlOptions = [
|
|
42
|
+
{
|
|
43
|
+
value: "ahmed",
|
|
44
|
+
label: "أحمد جلال",
|
|
45
|
+
addonText: "النظام",
|
|
46
|
+
itemType: "avatar" as const,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: "nora",
|
|
50
|
+
label: "نورا علي",
|
|
51
|
+
addonText: "المنتج",
|
|
52
|
+
itemType: "avatar" as const,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
value: "layla",
|
|
56
|
+
label: "ليلى حسن",
|
|
57
|
+
addonText: "الهندسة",
|
|
58
|
+
itemType: "avatar" as const,
|
|
59
|
+
},
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
export function AutocompleteDemo() {
|
|
63
|
+
return (
|
|
64
|
+
<div className="grid w-full gap-5 lg:grid-cols-2">
|
|
65
|
+
<div className="grid min-w-0 content-start gap-5">
|
|
66
|
+
<Autocomplete
|
|
67
|
+
className="mb-[var(--bh-space-13xl-160)]"
|
|
68
|
+
defaultOpen
|
|
69
|
+
defaultValue="ahmed"
|
|
70
|
+
helperText="Search by name, team, or keyword."
|
|
71
|
+
label="Owner"
|
|
72
|
+
options={peopleOptions}
|
|
73
|
+
placeholder="Search people"
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
<Autocomplete
|
|
77
|
+
defaultValue={["tokens", "inputs"]}
|
|
78
|
+
helperText="Selected values render with the Tag component."
|
|
79
|
+
label="Related work"
|
|
80
|
+
options={projectOptions}
|
|
81
|
+
placeholder="Add projects"
|
|
82
|
+
selectionMode="multiple"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div className="grid min-w-0 content-start gap-5">
|
|
87
|
+
<Autocomplete
|
|
88
|
+
label="Project"
|
|
89
|
+
options={projectOptions}
|
|
90
|
+
placeholder="Search projects"
|
|
91
|
+
variant="soft"
|
|
92
|
+
/>
|
|
93
|
+
|
|
94
|
+
<div dir="rtl" className="min-w-0">
|
|
95
|
+
<Autocomplete
|
|
96
|
+
className="pb-[var(--bh-space-13xl-160)] lg:pb-0"
|
|
97
|
+
defaultOpen
|
|
98
|
+
defaultValue="nora"
|
|
99
|
+
dir="rtl"
|
|
100
|
+
helperText="ابحث بالاسم أو الفريق."
|
|
101
|
+
label="المالك"
|
|
102
|
+
options={rtlOptions}
|
|
103
|
+
placeholder="ابحث عن شخص"
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
@@ -1,73 +1,128 @@
|
|
|
1
|
-
import { PlusIcon } from "lucide-react"
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
Avatar,
|
|
5
|
-
|
|
3
|
+
AvatarAction,
|
|
6
4
|
AvatarFallback,
|
|
7
5
|
AvatarGroup,
|
|
8
6
|
AvatarGroupCount,
|
|
7
|
+
AvatarIcon,
|
|
9
8
|
AvatarImage,
|
|
9
|
+
AvatarStatus,
|
|
10
10
|
} from "@/components/ui/avatar"
|
|
11
|
+
import { PlusIcon } from "lucide-react"
|
|
11
12
|
|
|
12
13
|
const avatarUrl = new URL("../assets/avatars/avatar-01.jpg", import.meta.url).href
|
|
13
14
|
|
|
15
|
+
const statusColumns = [
|
|
16
|
+
"available",
|
|
17
|
+
"available",
|
|
18
|
+
"busy",
|
|
19
|
+
"away",
|
|
20
|
+
"blocked",
|
|
21
|
+
] as const
|
|
22
|
+
|
|
23
|
+
const secondaryStatusColumns = [
|
|
24
|
+
"offline",
|
|
25
|
+
"available",
|
|
26
|
+
"busy",
|
|
27
|
+
"away",
|
|
28
|
+
"blocked",
|
|
29
|
+
] as const
|
|
30
|
+
|
|
14
31
|
export function AvatarDemo() {
|
|
15
32
|
return (
|
|
16
|
-
<div className="flex flex-col gap-
|
|
17
|
-
<div className="
|
|
18
|
-
|
|
33
|
+
<div className="flex flex-col gap-7">
|
|
34
|
+
<div className="grid w-fit grid-cols-5 gap-x-4 gap-y-4">
|
|
35
|
+
{statusColumns.map((status, index) => (
|
|
36
|
+
<Avatar key={`icon-${status}-${index}`} size="2xl">
|
|
37
|
+
<AvatarIcon />
|
|
38
|
+
{index === 0 ? <AvatarAction type="edit" size="medium" /> : null}
|
|
39
|
+
<AvatarStatus status={status} size="small" />
|
|
40
|
+
</Avatar>
|
|
41
|
+
))}
|
|
42
|
+
|
|
43
|
+
{secondaryStatusColumns.map((status) => (
|
|
44
|
+
<Avatar key={`initials-${status}`} size="2xl">
|
|
45
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
46
|
+
<AvatarStatus status={status} size="small" />
|
|
47
|
+
</Avatar>
|
|
48
|
+
))}
|
|
49
|
+
|
|
50
|
+
{secondaryStatusColumns.map((status) => (
|
|
51
|
+
<Avatar key={`image-${status}`} size="2xl">
|
|
52
|
+
<AvatarImage src={avatarUrl} alt="Profile portrait" />
|
|
53
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
54
|
+
<AvatarStatus status={status} size="small" />
|
|
55
|
+
</Avatar>
|
|
56
|
+
))}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div className="flex flex-wrap items-center gap-5 ps-7">
|
|
60
|
+
<Avatar size="2xl">
|
|
19
61
|
<AvatarImage src={avatarUrl} alt="Profile portrait" />
|
|
20
|
-
<AvatarFallback>
|
|
62
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
63
|
+
<AvatarAction type="edit" size="medium" />
|
|
21
64
|
</Avatar>
|
|
22
|
-
<Avatar>
|
|
23
|
-
<
|
|
65
|
+
<Avatar size="2xl">
|
|
66
|
+
<AvatarImage src={avatarUrl} alt="Profile portrait" />
|
|
67
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
68
|
+
<AvatarAction type="remove" size="medium" />
|
|
24
69
|
</Avatar>
|
|
25
|
-
<Avatar>
|
|
26
|
-
<AvatarImage src=
|
|
27
|
-
<AvatarFallback>
|
|
70
|
+
<Avatar size="2xl">
|
|
71
|
+
<AvatarImage src={avatarUrl} alt="Profile portrait" />
|
|
72
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
73
|
+
<AvatarAction type="verified" size="medium" />
|
|
28
74
|
</Avatar>
|
|
29
75
|
</div>
|
|
30
76
|
|
|
31
|
-
<div className="flex
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
77
|
+
<div className="flex items-center gap-3">
|
|
78
|
+
<AvatarGroup>
|
|
79
|
+
{Array.from({ length: 7 }).map((_, index) => (
|
|
80
|
+
<Avatar key={index} size="md">
|
|
81
|
+
<AvatarImage src={avatarUrl} alt="" />
|
|
82
|
+
<AvatarFallback>AG</AvatarFallback>
|
|
83
|
+
</Avatar>
|
|
84
|
+
))}
|
|
85
|
+
<AvatarGroupCount size="md">+10</AvatarGroupCount>
|
|
86
|
+
</AvatarGroup>
|
|
87
|
+
<Avatar
|
|
88
|
+
aria-label="Add member"
|
|
89
|
+
className="border border-dashed border-[var(--bh-border-subtle)] bg-[var(--bh-bg-default)] text-[var(--bh-content-subtle)]"
|
|
90
|
+
size="md"
|
|
91
|
+
>
|
|
92
|
+
<PlusIcon aria-hidden="true" className="size-4" />
|
|
42
93
|
</Avatar>
|
|
43
94
|
</div>
|
|
44
95
|
|
|
45
|
-
<
|
|
46
|
-
<Avatar>
|
|
47
|
-
<
|
|
96
|
+
<div className="flex items-center gap-3">
|
|
97
|
+
<Avatar size="xl">
|
|
98
|
+
<AvatarImage src={avatarUrl} alt="John Doe" />
|
|
99
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
100
|
+
<AvatarStatus status="available" size="small" />
|
|
48
101
|
</Avatar>
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
102
|
+
<div className="min-w-0">
|
|
103
|
+
<p className="text-sm font-semibold text-[var(--bh-content-default)]">
|
|
104
|
+
John Doe
|
|
105
|
+
</p>
|
|
106
|
+
<p className="text-sm text-[var(--bh-content-subtle)]">
|
|
107
|
+
johndoe@example.com
|
|
108
|
+
</p>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
57
111
|
|
|
58
|
-
<div
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
112
|
+
<div className="flex items-center gap-3">
|
|
113
|
+
<Avatar size="md">
|
|
114
|
+
<AvatarImage src={avatarUrl} alt="John Doe" />
|
|
115
|
+
<AvatarFallback>JD</AvatarFallback>
|
|
116
|
+
<AvatarStatus status="available" size="tiny" />
|
|
117
|
+
</Avatar>
|
|
118
|
+
<div className="min-w-0">
|
|
119
|
+
<p className="text-sm font-semibold text-[var(--bh-content-default)]">
|
|
120
|
+
John Doe
|
|
121
|
+
</p>
|
|
122
|
+
<p className="text-xs text-[var(--bh-content-subtle)]">
|
|
123
|
+
johndoe@example.com
|
|
124
|
+
</p>
|
|
125
|
+
</div>
|
|
71
126
|
</div>
|
|
72
127
|
</div>
|
|
73
128
|
)
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ArrowUpRightIcon,
|
|
3
3
|
BadgeCheckIcon,
|
|
4
4
|
BookmarkIcon,
|
|
5
|
+
ChevronRightIcon,
|
|
5
6
|
} from "lucide-react"
|
|
6
7
|
|
|
7
8
|
import { Badge } from "@/components/ui/badge"
|
|
@@ -48,6 +49,21 @@ export function BadgeDemo() {
|
|
|
48
49
|
<ArrowUpRightIcon data-icon="inline-end" data-rtl-flip="true" />
|
|
49
50
|
</a>
|
|
50
51
|
</Badge>
|
|
52
|
+
<Badge
|
|
53
|
+
asChild
|
|
54
|
+
color="blue"
|
|
55
|
+
splitAction
|
|
56
|
+
type="trailing-icon"
|
|
57
|
+
>
|
|
58
|
+
<a href="#badge">
|
|
59
|
+
In progress
|
|
60
|
+
<ChevronRightIcon
|
|
61
|
+
aria-hidden="true"
|
|
62
|
+
data-icon="inline-end"
|
|
63
|
+
data-rtl-flip="true"
|
|
64
|
+
/>
|
|
65
|
+
</a>
|
|
66
|
+
</Badge>
|
|
51
67
|
</div>
|
|
52
68
|
)
|
|
53
69
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
|
|
3
|
+
import { UserIcon } from "lucide-react"
|
|
4
|
+
|
|
3
5
|
import { Checkbox, CheckboxCard } from "@/components/ui/checkbox"
|
|
4
6
|
|
|
5
7
|
export function CheckboxDemo() {
|
|
@@ -56,12 +58,5 @@ export function CheckboxDemo() {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
function UserLineIcon() {
|
|
59
|
-
return
|
|
60
|
-
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
|
|
61
|
-
<path
|
|
62
|
-
fill="currentColor"
|
|
63
|
-
d="M4 22A8 8 0 0 1 20 22H18A6 6 0 0 0 6 22H4ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM12 11C14.21 11 16 9.21 16 7C16 4.79 14.21 3 12 3C9.79 3 8 4.79 8 7C8 9.21 9.79 11 12 11Z"
|
|
64
|
-
/>
|
|
65
|
-
</svg>
|
|
66
|
-
)
|
|
61
|
+
return <UserIcon aria-hidden="true" focusable="false" strokeWidth={2.1} />
|
|
67
62
|
}
|