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
|
@@ -12,58 +12,111 @@ const selectedRange: CalendarRange = {
|
|
|
12
12
|
to: new Date(2050, 7, 23),
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
const staticPopoverClassName =
|
|
16
|
+
"static left-auto top-auto mt-2 translate-x-0"
|
|
17
|
+
const datePickerClassName =
|
|
18
|
+
"w-[var(--bh-date-surface-width-picker)] max-w-full"
|
|
19
|
+
const dateRangePickerClassName = "w-max max-w-none"
|
|
20
|
+
|
|
15
21
|
export function DatePickerDemo() {
|
|
16
22
|
return (
|
|
17
23
|
<div className="grid gap-8">
|
|
18
|
-
<div className="
|
|
19
|
-
<
|
|
20
|
-
|
|
24
|
+
<div className="grid gap-6 lg:grid-cols-[repeat(auto-fit,minmax(260px,max-content))]">
|
|
25
|
+
<div data-date-demo-item>
|
|
26
|
+
<Calendar value={selectedDate} />
|
|
27
|
+
</div>
|
|
28
|
+
<div data-date-demo-item>
|
|
29
|
+
<Calendar view="month-year" value={selectedDate} />
|
|
30
|
+
</div>
|
|
21
31
|
</div>
|
|
22
32
|
|
|
23
33
|
<div className="grid gap-6 xl:grid-cols-2">
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
<div data-date-demo-item>
|
|
35
|
+
<DatePicker
|
|
36
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
37
|
+
className={datePickerClassName}
|
|
38
|
+
defaultValue={selectedDate}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
<div data-date-demo-item dir="rtl">
|
|
27
42
|
<DatePicker
|
|
43
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
44
|
+
className={datePickerClassName}
|
|
28
45
|
dir="rtl"
|
|
29
|
-
placeholder="\u0627\u062e\u062a\u0631 \u062a\u0627\u0631\u064a\u062e"
|
|
46
|
+
placeholder={"\u0627\u062e\u062a\u0631 \u062a\u0627\u0631\u064a\u062e"}
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div className="grid gap-6 xl:grid-cols-2">
|
|
52
|
+
<div data-date-demo-item>
|
|
53
|
+
<DatePicker
|
|
54
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
55
|
+
className={datePickerClassName}
|
|
56
|
+
defaultOpen
|
|
57
|
+
defaultValue={selectedDate}
|
|
30
58
|
/>
|
|
31
59
|
</div>
|
|
32
|
-
<div dir="rtl">
|
|
60
|
+
<div data-date-demo-item dir="rtl">
|
|
33
61
|
<DatePicker
|
|
62
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
63
|
+
className={datePickerClassName}
|
|
34
64
|
defaultOpen
|
|
35
65
|
defaultValue={selectedDate}
|
|
36
66
|
dir="rtl"
|
|
37
|
-
placeholder="\u0627\u062e\u062a\u0631 \u062a\u0627\u0631\u064a\u062e"
|
|
67
|
+
placeholder={"\u0627\u062e\u062a\u0631 \u062a\u0627\u0631\u064a\u062e"}
|
|
38
68
|
/>
|
|
39
69
|
</div>
|
|
40
70
|
</div>
|
|
41
71
|
|
|
42
72
|
<div className="grid gap-6 overflow-x-auto">
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
73
|
+
<div data-date-demo-item>
|
|
74
|
+
<RangeCalendar value={selectedRange} />
|
|
75
|
+
</div>
|
|
76
|
+
<div data-date-demo-item>
|
|
77
|
+
<RangeCalendar type="double-with-presets" value={selectedRange} />
|
|
78
|
+
</div>
|
|
79
|
+
<div data-date-demo-item>
|
|
80
|
+
<RangeCalendar type="single" value={selectedRange} />
|
|
81
|
+
</div>
|
|
46
82
|
</div>
|
|
47
83
|
|
|
48
84
|
<div className="grid gap-6 xl:grid-cols-2">
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
85
|
+
<div data-date-demo-item className="overflow-x-auto pb-2">
|
|
86
|
+
<DateRangePicker
|
|
87
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
88
|
+
className={dateRangePickerClassName}
|
|
89
|
+
value={selectedRange}
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
<div data-date-demo-item className="overflow-x-auto pb-2" dir="rtl">
|
|
56
93
|
<DateRangePicker
|
|
94
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
95
|
+
className={dateRangePickerClassName}
|
|
57
96
|
dir="rtl"
|
|
58
|
-
placeholder="\u0627\u062e\u062a\u0631 \u0646\u0637\u0627\u0642 \u0627\u0644\u062a\u0627\u0631\u064a\u062e"
|
|
97
|
+
placeholder={"\u0627\u062e\u062a\u0631 \u0646\u0637\u0627\u0642 \u0627\u0644\u062a\u0627\u0631\u064a\u062e"}
|
|
98
|
+
value={selectedRange}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div className="grid gap-6">
|
|
104
|
+
<div data-date-demo-item className="overflow-x-auto pb-2">
|
|
105
|
+
<DateRangePicker
|
|
106
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
107
|
+
className={dateRangePickerClassName}
|
|
108
|
+
defaultOpen
|
|
109
|
+
type="double-with-presets"
|
|
59
110
|
value={selectedRange}
|
|
60
111
|
/>
|
|
61
112
|
</div>
|
|
62
|
-
<div dir="rtl">
|
|
113
|
+
<div data-date-demo-item className="overflow-x-auto pb-2" dir="rtl">
|
|
63
114
|
<DateRangePicker
|
|
115
|
+
calendarProps={{ className: staticPopoverClassName }}
|
|
116
|
+
className={dateRangePickerClassName}
|
|
64
117
|
defaultOpen
|
|
65
118
|
dir="rtl"
|
|
66
|
-
placeholder="\u064a\u0648\u0645 / \u0634\u0647\u0631 / \u0633\u0646\u0629"
|
|
119
|
+
placeholder={"\u064a\u0648\u0645 / \u0634\u0647\u0631 / \u0633\u0646\u0629"}
|
|
67
120
|
type="double-with-presets"
|
|
68
121
|
value={selectedRange}
|
|
69
122
|
/>
|
|
@@ -1,23 +1,48 @@
|
|
|
1
1
|
import { Banner } from "@/components/ui/expanded/Banner"
|
|
2
|
-
import { BannerBoard as ExpandedBannerBoard } from "@/components/ui/expanded/BannerBoard"
|
|
3
2
|
|
|
4
3
|
const bannerDemoCopy = {
|
|
5
4
|
actionLabel: "Button",
|
|
6
5
|
ariaLabel: "Announcement banner",
|
|
7
6
|
closeLabel: "Dismiss banner",
|
|
8
7
|
description: "Discover the Latest Updates in Our New Release",
|
|
9
|
-
inputAriaLabel: "Banner input",
|
|
10
|
-
inputPlaceholder: "Placeholder",
|
|
11
8
|
linkLabel: "Link button",
|
|
12
9
|
title: "Big news!",
|
|
13
10
|
}
|
|
14
11
|
|
|
12
|
+
const rtlBannerDemoCopy = {
|
|
13
|
+
actionLabel: "تطبيق",
|
|
14
|
+
ariaLabel: "شريط إعلان",
|
|
15
|
+
closeLabel: "إغلاق",
|
|
16
|
+
description: "اكتشف آخر التحديثات في إصدارنا الجديد",
|
|
17
|
+
linkLabel: "الرابط",
|
|
18
|
+
title: "أخبار مهمة!",
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
export function BannerDemo() {
|
|
16
22
|
return (
|
|
17
|
-
<div className="grid gap-
|
|
23
|
+
<div className="grid gap-4">
|
|
18
24
|
<Banner {...bannerDemoCopy} />
|
|
19
|
-
<Banner {...bannerDemoCopy} type="
|
|
20
|
-
<
|
|
25
|
+
<Banner {...bannerDemoCopy} type="single-action-inline" />
|
|
26
|
+
<Banner {...bannerDemoCopy} size="full-width" type="single-action" />
|
|
27
|
+
<Banner
|
|
28
|
+
{...bannerDemoCopy}
|
|
29
|
+
color="grey"
|
|
30
|
+
content="title-description"
|
|
31
|
+
size="full-width"
|
|
32
|
+
type="single-action"
|
|
33
|
+
/>
|
|
34
|
+
<Banner
|
|
35
|
+
{...bannerDemoCopy}
|
|
36
|
+
color="brand-light"
|
|
37
|
+
content="title-description"
|
|
38
|
+
type="single-action-inline"
|
|
39
|
+
/>
|
|
40
|
+
<Banner
|
|
41
|
+
{...rtlBannerDemoCopy}
|
|
42
|
+
content="title-description"
|
|
43
|
+
dir="rtl"
|
|
44
|
+
type="single-action-inline"
|
|
45
|
+
/>
|
|
21
46
|
</div>
|
|
22
47
|
)
|
|
23
48
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BreadcrumbFolderIcon,
|
|
3
|
+
BreadcrumbHomeIcon,
|
|
4
|
+
Breadcrumbs,
|
|
5
|
+
type BreadcrumbItem,
|
|
6
|
+
} from "@/components/ui/expanded/Breadcrumbs"
|
|
7
|
+
|
|
8
|
+
const breadcrumbItems: BreadcrumbItem[] = [
|
|
9
|
+
{ label: "Home", href: "#", icon: <BreadcrumbHomeIcon /> },
|
|
10
|
+
{ label: "Design system", href: "#", icon: <BreadcrumbFolderIcon /> },
|
|
11
|
+
{ label: "Components", href: "#" },
|
|
12
|
+
{ label: "Breadcrumbs", current: true },
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
const longBreadcrumbItems: BreadcrumbItem[] = [
|
|
16
|
+
{ label: "Home", href: "#", icon: <BreadcrumbHomeIcon /> },
|
|
17
|
+
{ label: "Workspace", href: "#", icon: <BreadcrumbFolderIcon /> },
|
|
18
|
+
{ label: "Design System", href: "#" },
|
|
19
|
+
{ label: "Components", href: "#" },
|
|
20
|
+
{ label: "Navigation", href: "#" },
|
|
21
|
+
{ label: "Breadcrumbs", current: true },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const rtlBreadcrumbItems: BreadcrumbItem[] = [
|
|
25
|
+
{ label: "\u0627\u0644\u0631\u0626\u064a\u0633\u064a\u0629", href: "#", icon: <BreadcrumbHomeIcon /> },
|
|
26
|
+
{ label: "\u0627\u0644\u0646\u0638\u0627\u0645", href: "#", icon: <BreadcrumbFolderIcon /> },
|
|
27
|
+
{ label: "\u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062a", current: true },
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
export function BreadcrumbsDemo() {
|
|
31
|
+
return (
|
|
32
|
+
<div className="grid gap-4">
|
|
33
|
+
<Breadcrumbs aria-label="Breadcrumb" items={breadcrumbItems} overflowLabel="More" />
|
|
34
|
+
<Breadcrumbs
|
|
35
|
+
aria-label="Breadcrumb"
|
|
36
|
+
items={breadcrumbItems}
|
|
37
|
+
overflowLabel="More"
|
|
38
|
+
separator="chevron"
|
|
39
|
+
style="raised"
|
|
40
|
+
/>
|
|
41
|
+
<Breadcrumbs
|
|
42
|
+
aria-label="Breadcrumb"
|
|
43
|
+
items={longBreadcrumbItems}
|
|
44
|
+
maxItems={4}
|
|
45
|
+
overflowLabel="More"
|
|
46
|
+
separator="chevron"
|
|
47
|
+
style="raised"
|
|
48
|
+
/>
|
|
49
|
+
<Breadcrumbs
|
|
50
|
+
aria-label={"\u0627\u0644\u0645\u0633\u0627\u0631"}
|
|
51
|
+
dir="rtl"
|
|
52
|
+
items={rtlBreadcrumbItems}
|
|
53
|
+
overflowLabel={"\u0627\u0644\u0645\u0632\u064a\u062f"}
|
|
54
|
+
separator="chevron"
|
|
55
|
+
style="raised"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -1,5 +1,101 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
BoxIcon,
|
|
4
|
+
CheckIcon,
|
|
5
|
+
CloudIcon,
|
|
6
|
+
EyeIcon,
|
|
7
|
+
FileTextIcon,
|
|
8
|
+
GitPullRequestIcon,
|
|
9
|
+
LayoutGridIcon,
|
|
10
|
+
MessageSquareIcon,
|
|
11
|
+
PencilIcon,
|
|
12
|
+
RefreshCcwIcon,
|
|
13
|
+
SearchIcon,
|
|
14
|
+
Settings2Icon,
|
|
15
|
+
ShieldCheckIcon,
|
|
16
|
+
WorkflowIcon,
|
|
17
|
+
XIcon,
|
|
18
|
+
} from "lucide-react"
|
|
19
|
+
|
|
20
|
+
import { Avatar, AvatarIcon, AvatarStatus } from "@/components/ui/avatar"
|
|
21
|
+
import { Badge } from "@/components/ui/badge"
|
|
22
|
+
import { Button } from "@/components/ui/button"
|
|
23
|
+
import {
|
|
24
|
+
Menu,
|
|
25
|
+
MenuItem,
|
|
26
|
+
MenuItemDescription,
|
|
27
|
+
MenuItemText,
|
|
28
|
+
MenuItemTitle,
|
|
29
|
+
} from "@/components/ui/menu"
|
|
30
|
+
import { ModalBody, ModalHeader, ModalSurface } from "@/components/ui/modal"
|
|
31
|
+
import {
|
|
32
|
+
Toolbar,
|
|
33
|
+
ToolbarButton,
|
|
34
|
+
ToolbarSearch,
|
|
35
|
+
ToolbarSection,
|
|
36
|
+
} from "@/components/ui/toolbar"
|
|
1
37
|
import { CommandBar } from "@/components/ui/expanded/CommandBar"
|
|
2
38
|
|
|
39
|
+
type ToolTone = "neutral" | "blue" | "green" | "amber" | "purple" | "sky"
|
|
40
|
+
type ToolIcon = React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
41
|
+
|
|
42
|
+
type ToolItem = {
|
|
43
|
+
added?: boolean
|
|
44
|
+
description?: string
|
|
45
|
+
icon: ToolIcon
|
|
46
|
+
title: string
|
|
47
|
+
tone?: ToolTone
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const popularTools: ToolItem[] = [
|
|
51
|
+
{
|
|
52
|
+
added: true,
|
|
53
|
+
icon: EyeIcon,
|
|
54
|
+
title: "View repositories & issues",
|
|
55
|
+
tone: "green",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
description: "Create, comment, update issues",
|
|
59
|
+
icon: PencilIcon,
|
|
60
|
+
title: "Create & update issues",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
description: "Use commit and repo activity",
|
|
64
|
+
icon: RefreshCcwIcon,
|
|
65
|
+
title: "Sync commits and activity",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
description: "Review and update pull requests",
|
|
69
|
+
icon: GitPullRequestIcon,
|
|
70
|
+
title: "Manage pull requests",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
description: "Run GitHub workflows",
|
|
74
|
+
icon: WorkflowIcon,
|
|
75
|
+
title: "Trigger workflows & automations",
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
const serverTools: ToolItem[] = [
|
|
80
|
+
{ icon: BoxIcon, title: "Box", tone: "blue" },
|
|
81
|
+
{ icon: CloudIcon, title: "Google Drive", tone: "green" },
|
|
82
|
+
{ icon: Settings2Icon, title: "Hubspot", tone: "amber" },
|
|
83
|
+
{ icon: MessageSquareIcon, title: "Intercom", tone: "sky" },
|
|
84
|
+
{ icon: WorkflowIcon, title: "Jira", tone: "blue" },
|
|
85
|
+
{ icon: FileTextIcon, title: "Notion" },
|
|
86
|
+
{ icon: ShieldCheckIcon, title: "Okta" },
|
|
87
|
+
{ icon: CloudIcon, title: "Salesforce", tone: "sky" },
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
const toolToneClassNames: Record<ToolTone, string> = {
|
|
91
|
+
amber: "text-[var(--bh-content-accent-amber-default)]",
|
|
92
|
+
blue: "text-[var(--bh-content-accent-blue-default)]",
|
|
93
|
+
green: "text-[var(--bh-content-accent-green-default)]",
|
|
94
|
+
neutral: "text-[var(--bh-content-subtle)]",
|
|
95
|
+
purple: "text-[var(--bh-content-accent-purple-default)]",
|
|
96
|
+
sky: "text-[var(--bh-content-accent-sky-default)]",
|
|
97
|
+
}
|
|
98
|
+
|
|
3
99
|
export function CommandBarDemo() {
|
|
4
100
|
return (
|
|
5
101
|
<div className="grid gap-6">
|
|
@@ -8,3 +104,143 @@ export function CommandBarDemo() {
|
|
|
8
104
|
</div>
|
|
9
105
|
)
|
|
10
106
|
}
|
|
107
|
+
|
|
108
|
+
export function AddToolPickerExample() {
|
|
109
|
+
return (
|
|
110
|
+
<ModalSurface
|
|
111
|
+
aria-label="Add tool command example"
|
|
112
|
+
className={[
|
|
113
|
+
"[--bh-modal-width:calc(var(--bh-space-19xl-384)+var(--bh-space-18xl-320)+var(--bh-space-8xl-48))]",
|
|
114
|
+
"rounded-[var(--bh-radius-6xl-28)]",
|
|
115
|
+
].join(" ")}
|
|
116
|
+
size="lg"
|
|
117
|
+
>
|
|
118
|
+
<ModalHeader className="items-start justify-between px-[var(--bh-space-5xl-24)] pb-[var(--bh-space-lg-10)] pe-[var(--bh-space-5xl-24)] pt-[var(--bh-space-5xl-24)]">
|
|
119
|
+
<h2 className="min-w-0 flex-1 text-start text-[length:var(--bh-text-heading-sm-semibold-font-size)] font-[var(--bh-text-heading-sm-semibold-font-weight)] leading-[var(--bh-text-heading-sm-semibold-line-height)] tracking-[var(--bh-text-heading-sm-semibold-letter-spacing)] text-[var(--bh-content-default)]">
|
|
120
|
+
Add tool
|
|
121
|
+
</h2>
|
|
122
|
+
<Button aria-label="Close add tool" size="icon" type="button" variant="ghost">
|
|
123
|
+
<XIcon aria-hidden="true" />
|
|
124
|
+
</Button>
|
|
125
|
+
</ModalHeader>
|
|
126
|
+
|
|
127
|
+
<ModalBody className="grid w-full gap-[var(--bh-space-4xl-20)] px-[var(--bh-space-5xl-24)] pb-[var(--bh-space-6xl-32)] pt-0">
|
|
128
|
+
<ToolbarSearch
|
|
129
|
+
aria-label="Search tools"
|
|
130
|
+
icon={<SearchIcon aria-hidden="true" />}
|
|
131
|
+
placeholder="Search..."
|
|
132
|
+
width="full"
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<Toolbar aria-label="Tool source filters" className="overflow-x-auto" wrap>
|
|
136
|
+
<ToolbarSection wrap>
|
|
137
|
+
<ToolCategory icon={Settings2Icon}>All</ToolCategory>
|
|
138
|
+
<ToolCategory icon={LayoutGridIcon}>Apps</ToolCategory>
|
|
139
|
+
<ToolCategory active icon={LayoutGridIcon}>
|
|
140
|
+
MCP
|
|
141
|
+
</ToolCategory>
|
|
142
|
+
</ToolbarSection>
|
|
143
|
+
</Toolbar>
|
|
144
|
+
|
|
145
|
+
<ToolSection items={popularTools} title="Popular" />
|
|
146
|
+
<ToolSection items={serverTools} title="Servers" />
|
|
147
|
+
</ModalBody>
|
|
148
|
+
</ModalSurface>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function ToolCategory({
|
|
153
|
+
active = false,
|
|
154
|
+
children,
|
|
155
|
+
icon: Icon,
|
|
156
|
+
}: {
|
|
157
|
+
active?: boolean
|
|
158
|
+
children: React.ReactNode
|
|
159
|
+
icon: ToolIcon
|
|
160
|
+
}) {
|
|
161
|
+
return (
|
|
162
|
+
<ToolbarButton
|
|
163
|
+
aria-pressed={active}
|
|
164
|
+
className={[
|
|
165
|
+
"rounded-[var(--bh-radius-none)] border-b-[length:var(--bh-border-width-strong)] px-[var(--bh-space-xs-4)]",
|
|
166
|
+
active
|
|
167
|
+
? "border-b-[var(--bh-border-accent-purple-strong)] text-[var(--bh-content-accent-purple-default)]"
|
|
168
|
+
: "border-b-transparent text-[var(--bh-content-subtle)]",
|
|
169
|
+
].join(" ")}
|
|
170
|
+
size="sm"
|
|
171
|
+
type="button"
|
|
172
|
+
variant="ghost"
|
|
173
|
+
>
|
|
174
|
+
<Icon aria-hidden="true" data-icon="inline-start" />
|
|
175
|
+
{children}
|
|
176
|
+
</ToolbarButton>
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function ToolSection({ items, title }: { items: ToolItem[]; title: string }) {
|
|
181
|
+
return (
|
|
182
|
+
<section className="grid gap-[var(--bh-space-xl-12)]" aria-label={title}>
|
|
183
|
+
<h3 className="text-start text-[length:var(--bh-text-body-md-medium-font-size)] font-[var(--bh-text-body-md-medium-font-weight)] leading-[var(--bh-text-body-md-medium-line-height)] tracking-[var(--bh-text-body-md-medium-letter-spacing)] text-[var(--bh-content-subtle)]">
|
|
184
|
+
{title}
|
|
185
|
+
</h3>
|
|
186
|
+
<div className="grid gap-[var(--bh-space-md-8)] sm:grid-cols-2">
|
|
187
|
+
{items.map((item) => (
|
|
188
|
+
<ToolRow item={item} key={item.title} />
|
|
189
|
+
))}
|
|
190
|
+
</div>
|
|
191
|
+
</section>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function ToolRow({ item }: { item: ToolItem }) {
|
|
196
|
+
const Icon = item.icon
|
|
197
|
+
const tone = item.tone ?? "neutral"
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<Menu
|
|
201
|
+
aria-label={`${item.title} tool action`}
|
|
202
|
+
className="w-full bg-transparent p-0 shadow-none"
|
|
203
|
+
width="auto"
|
|
204
|
+
>
|
|
205
|
+
<MenuItem
|
|
206
|
+
aria-label={item.title}
|
|
207
|
+
className="min-h-[var(--bh-space-8xl-48)] px-[var(--bh-space-xs-4)] py-[var(--bh-space-xxs-2)]"
|
|
208
|
+
kind="multiline"
|
|
209
|
+
role="menuitem"
|
|
210
|
+
>
|
|
211
|
+
<Avatar shape="rounded" size="lg">
|
|
212
|
+
<AvatarIcon
|
|
213
|
+
className={[
|
|
214
|
+
"border border-[var(--bh-border-subtle)]",
|
|
215
|
+
"[&_svg]:size-[var(--bh-space-4xl-20)]",
|
|
216
|
+
toolToneClassNames[tone],
|
|
217
|
+
].join(" ")}
|
|
218
|
+
size="lg"
|
|
219
|
+
>
|
|
220
|
+
<Icon aria-hidden="true" strokeWidth={2} />
|
|
221
|
+
</AvatarIcon>
|
|
222
|
+
{item.added ? <AvatarStatus size="small" status="available" /> : null}
|
|
223
|
+
</Avatar>
|
|
224
|
+
<MenuItemText>
|
|
225
|
+
<MenuItemTitle className="font-[var(--bh-text-body-md-medium-font-weight)]">
|
|
226
|
+
{item.title}
|
|
227
|
+
</MenuItemTitle>
|
|
228
|
+
{item.added ? (
|
|
229
|
+
<Badge
|
|
230
|
+
badgeStyle="light"
|
|
231
|
+
className="self-start"
|
|
232
|
+
color="green"
|
|
233
|
+
size="sm"
|
|
234
|
+
type="leading-icon"
|
|
235
|
+
>
|
|
236
|
+
<CheckIcon aria-hidden="true" />
|
|
237
|
+
Added
|
|
238
|
+
</Badge>
|
|
239
|
+
) : item.description ? (
|
|
240
|
+
<MenuItemDescription>{item.description}</MenuItemDescription>
|
|
241
|
+
) : null}
|
|
242
|
+
</MenuItemText>
|
|
243
|
+
</MenuItem>
|
|
244
|
+
</Menu>
|
|
245
|
+
)
|
|
246
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { InboxIcon, PlusIcon, SearchIcon } from "lucide-react"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
EmptyState,
|
|
5
|
+
type EmptyStateAction,
|
|
6
|
+
} from "@/components/ui/expanded/EmptyState"
|
|
7
|
+
|
|
8
|
+
const searchActions: EmptyStateAction[] = [
|
|
9
|
+
{ label: "Reset filters", variant: "secondary" },
|
|
10
|
+
{ label: "Create item" },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const inboxActions: EmptyStateAction[] = [
|
|
14
|
+
{
|
|
15
|
+
icon: <PlusIcon data-icon="inline-start" />,
|
|
16
|
+
label: "Add record",
|
|
17
|
+
},
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
export function EmptyStateDemo() {
|
|
21
|
+
return (
|
|
22
|
+
<div className="grid gap-6">
|
|
23
|
+
<EmptyState
|
|
24
|
+
actions={searchActions}
|
|
25
|
+
description="Try adjusting your search or filters"
|
|
26
|
+
icon={<SearchIcon />}
|
|
27
|
+
title="No results found"
|
|
28
|
+
/>
|
|
29
|
+
<EmptyState
|
|
30
|
+
actions={inboxActions}
|
|
31
|
+
align="start"
|
|
32
|
+
description="Create a record to start tracking this workflow."
|
|
33
|
+
icon={<InboxIcon />}
|
|
34
|
+
size="compact"
|
|
35
|
+
title="Nothing here yet"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FileUpload,
|
|
3
|
+
type FileUploadFile,
|
|
4
|
+
} from "@/components/ui/expanded/FileUpload"
|
|
5
|
+
|
|
6
|
+
const uploadFiles: FileUploadFile[] = [
|
|
7
|
+
{
|
|
8
|
+
id: "uploaded",
|
|
9
|
+
name: "file-name.pdf",
|
|
10
|
+
sizeLabel: "32mb",
|
|
11
|
+
status: "uploaded",
|
|
12
|
+
versionLabel: "v1.2.2",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "uploading",
|
|
16
|
+
name: "file-name.pdf",
|
|
17
|
+
sizeLabel: "32mb",
|
|
18
|
+
status: "uploading",
|
|
19
|
+
versionLabel: "v1.2.2",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "progress",
|
|
23
|
+
name: "file-name.pdf",
|
|
24
|
+
progress: 40,
|
|
25
|
+
sizeLabel: "32 KB",
|
|
26
|
+
status: "uploading-progress",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
errorLabel: "Upload failed",
|
|
30
|
+
id: "error",
|
|
31
|
+
name: "file-name.pdf",
|
|
32
|
+
sizeLabel: "32mb",
|
|
33
|
+
status: "error",
|
|
34
|
+
versionLabel: "v1.2.2",
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
export function FileUploadDemo() {
|
|
39
|
+
return (
|
|
40
|
+
<div className="grid items-start gap-5 xl:grid-cols-2">
|
|
41
|
+
<FileUpload
|
|
42
|
+
files={uploadFiles}
|
|
43
|
+
multiple
|
|
44
|
+
/>
|
|
45
|
+
<FileUpload
|
|
46
|
+
files={uploadFiles}
|
|
47
|
+
size="sm"
|
|
48
|
+
/>
|
|
49
|
+
<FileUpload
|
|
50
|
+
dropzoneState="hover"
|
|
51
|
+
files={uploadFiles.slice(0, 1)}
|
|
52
|
+
variant="button"
|
|
53
|
+
/>
|
|
54
|
+
<FileUpload
|
|
55
|
+
disabled
|
|
56
|
+
files={[]}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button"
|
|
1
2
|
import { Steps, type StepItem } from "@/components/ui/expanded/Steps"
|
|
2
3
|
|
|
3
4
|
const stepItems: StepItem[] = Array.from({ length: 6 }, (_, index) => ({
|
|
5
|
+
actions: (
|
|
6
|
+
<>
|
|
7
|
+
<Button size="sm" type="button" variant="default">
|
|
8
|
+
Button
|
|
9
|
+
</Button>
|
|
10
|
+
<Button size="sm" type="button" variant="secondary">
|
|
11
|
+
Button
|
|
12
|
+
</Button>
|
|
13
|
+
</>
|
|
14
|
+
),
|
|
4
15
|
caption: "Caption",
|
|
5
16
|
label: "Label",
|
|
6
17
|
number: index + 1,
|