banhaten 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +93 -328
  2. package/banhaten.config.example.json +1 -1
  3. package/docs/design-system/README.md +11 -0
  4. package/docs/design-system/appearance-presets.md +184 -0
  5. package/docs/design-system/appearances/default.md +94 -0
  6. package/docs/design-system/appearances/rounded.md +95 -0
  7. package/docs/design-system/appearances/sharp.md +95 -0
  8. package/docs/design-system/component-showcase-consistency-report.md +217 -0
  9. package/docs/design-system/component-token-consistency-audit.md +163 -0
  10. package/docs/design-system/components/README.md +74 -0
  11. package/docs/design-system/components/accordion.md +51 -0
  12. package/docs/design-system/components/activity-feed.md +92 -0
  13. package/docs/design-system/components/alert-dialog.md +70 -0
  14. package/docs/design-system/components/alert.md +79 -0
  15. package/docs/design-system/components/aspect-ratio.md +44 -0
  16. package/docs/design-system/components/attribute.md +87 -0
  17. package/docs/design-system/components/autocomplete.md +74 -0
  18. package/docs/design-system/components/avatar.md +52 -0
  19. package/docs/design-system/components/badge.md +53 -0
  20. package/docs/design-system/components/banner.md +85 -0
  21. package/docs/design-system/components/breadcrumbs.md +174 -0
  22. package/docs/design-system/components/button-group.md +83 -0
  23. package/docs/design-system/components/button.md +77 -0
  24. package/docs/design-system/components/card.md +78 -0
  25. package/docs/design-system/components/carousel.md +44 -0
  26. package/docs/design-system/components/catalog-components.md +45 -0
  27. package/docs/design-system/components/chart.md +43 -0
  28. package/docs/design-system/components/checkbox.md +52 -0
  29. package/docs/design-system/components/collapsible.md +48 -0
  30. package/docs/design-system/components/command-bar.md +57 -0
  31. package/docs/design-system/components/command.md +60 -0
  32. package/docs/design-system/components/context-menu.md +44 -0
  33. package/docs/design-system/components/date-picker.md +77 -0
  34. package/docs/design-system/components/divider.md +101 -0
  35. package/docs/design-system/components/empty-state.md +55 -0
  36. package/docs/design-system/components/field.md +69 -0
  37. package/docs/design-system/components/file-upload.md +185 -0
  38. package/docs/design-system/components/hover-card.md +46 -0
  39. package/docs/design-system/components/icons.md +48 -0
  40. package/docs/design-system/components/input-group.md +56 -0
  41. package/docs/design-system/components/input-otp.md +55 -0
  42. package/docs/design-system/components/input.md +48 -0
  43. package/docs/design-system/components/kbd.md +44 -0
  44. package/docs/design-system/components/label.md +48 -0
  45. package/docs/design-system/components/menu.md +59 -0
  46. package/docs/design-system/components/menubar.md +45 -0
  47. package/docs/design-system/components/modal.md +98 -0
  48. package/docs/design-system/components/native-select.md +52 -0
  49. package/docs/design-system/components/navigation-menu.md +48 -0
  50. package/docs/design-system/components/onboarding-step-list-item.md +80 -0
  51. package/docs/design-system/components/page-header.md +84 -0
  52. package/docs/design-system/components/pagination.md +49 -0
  53. package/docs/design-system/components/popover.md +58 -0
  54. package/docs/design-system/components/progress-slider.md +48 -0
  55. package/docs/design-system/components/progress.md +75 -0
  56. package/docs/design-system/components/radio-card.md +49 -0
  57. package/docs/design-system/components/radio-group.md +55 -0
  58. package/docs/design-system/components/resizable.md +42 -0
  59. package/docs/design-system/components/scroll-area.md +45 -0
  60. package/docs/design-system/components/select.md +50 -0
  61. package/docs/design-system/components/sheet.md +65 -0
  62. package/docs/design-system/components/sidebar.md +68 -0
  63. package/docs/design-system/components/skeleton.md +73 -0
  64. package/docs/design-system/components/slideout.md +63 -0
  65. package/docs/design-system/components/slider.md +61 -0
  66. package/docs/design-system/components/social-button.md +47 -0
  67. package/docs/design-system/components/spinner.md +61 -0
  68. package/docs/design-system/components/steps.md +63 -0
  69. package/docs/design-system/components/table.md +397 -0
  70. package/docs/design-system/components/tabs.md +52 -0
  71. package/docs/design-system/components/tag.md +78 -0
  72. package/docs/design-system/components/textarea.md +48 -0
  73. package/docs/design-system/components/timeline.md +81 -0
  74. package/docs/design-system/components/toast.md +56 -0
  75. package/docs/design-system/components/toggle.md +79 -0
  76. package/docs/design-system/components/toolbar.md +85 -0
  77. package/docs/design-system/components/tooltip.md +90 -0
  78. package/docs/design-system/components/typography.md +18 -0
  79. package/docs/design-system/design-system-test-missing-items.md +368 -0
  80. package/docs/design-system/icons.md +69 -0
  81. package/docs/design-system/registry-and-cli.md +41 -0
  82. package/docs/design-system/tabs.md +53 -0
  83. package/docs/design-system/token-governance.md +38 -0
  84. package/package.json +83 -65
  85. package/registry/components/alert-dialog.tsx +297 -0
  86. package/registry/components/aspect-ratio.tsx +30 -0
  87. package/registry/components/carousel.tsx +234 -0
  88. package/registry/components/chart.tsx +170 -0
  89. package/registry/components/collapsible.tsx +69 -0
  90. package/registry/components/command.tsx +174 -0
  91. package/registry/components/context-menu.tsx +236 -0
  92. package/registry/components/date-picker.tsx +1 -1
  93. package/registry/components/expanded/PageHeader.tsx +1 -1
  94. package/registry/components/expanded/breadcrumbs.css +139 -139
  95. package/registry/components/expanded/catalogComponentsShowcase.css +83 -83
  96. package/registry/components/expanded/steps.css +274 -274
  97. package/registry/components/expanded/timeline.css +264 -264
  98. package/registry/components/field.tsx +230 -0
  99. package/registry/components/hover-card.tsx +48 -0
  100. package/registry/components/input-group.tsx +130 -0
  101. package/registry/components/input.tsx +2 -2
  102. package/registry/components/kbd.tsx +44 -0
  103. package/registry/components/label.tsx +78 -0
  104. package/registry/components/menu.tsx +3 -1
  105. package/registry/components/menubar.tsx +226 -0
  106. package/registry/components/modal.tsx +109 -76
  107. package/registry/components/native-select.tsx +205 -0
  108. package/registry/components/navigation-menu.tsx +171 -0
  109. package/registry/components/radio-group.tsx +1 -1
  110. package/registry/components/resizable.tsx +74 -0
  111. package/registry/components/scroll-area.tsx +67 -0
  112. package/registry/components/select.tsx +2 -4
  113. package/registry/components/sheet.tsx +305 -0
  114. package/registry/components/sidebar.tsx +352 -0
  115. package/registry/components/social-button.tsx +74 -10
  116. package/registry/components/{expanded/tabs.css → tabs.css} +127 -106
  117. package/registry/components/tabs.tsx +242 -0
  118. package/registry/components/textarea.tsx +1 -1
  119. package/registry/components/toast.tsx +131 -0
  120. package/registry/examples/alert-dialog-demo.tsx +42 -0
  121. package/registry/examples/aspect-ratio-demo.tsx +11 -0
  122. package/registry/examples/carousel-demo.tsx +25 -0
  123. package/registry/examples/chart-demo.tsx +33 -0
  124. package/registry/examples/collapsible-demo.tsx +16 -0
  125. package/registry/examples/command-demo.tsx +42 -0
  126. package/registry/examples/context-menu-demo.tsx +29 -0
  127. package/registry/examples/expanded/tabs-demo.tsx +1 -1
  128. package/registry/examples/field-demo.tsx +51 -0
  129. package/registry/examples/hover-card-demo.tsx +23 -0
  130. package/registry/examples/input-group-demo.tsx +16 -0
  131. package/registry/examples/kbd-demo.tsx +11 -0
  132. package/registry/examples/label-demo.tsx +20 -0
  133. package/registry/examples/menubar-demo.tsx +34 -0
  134. package/registry/examples/native-select-demo.tsx +16 -0
  135. package/registry/examples/navigation-menu-demo.tsx +29 -0
  136. package/registry/examples/resizable-demo.tsx +22 -0
  137. package/registry/examples/scroll-area-demo.tsx +15 -0
  138. package/registry/examples/sheet-demo.tsx +47 -0
  139. package/registry/examples/sidebar-demo.tsx +55 -0
  140. package/registry/examples/tabs-demo.tsx +13 -0
  141. package/registry/examples/toast-demo.tsx +35 -0
  142. package/registry/index.json +655 -11
  143. package/registry/styles/globals.css +4733 -4690
  144. package/registry.json +1612 -0
  145. package/schema/config.schema.json +48 -0
  146. package/schema/registry.schema.json +85 -0
  147. package/schema/tokens.schema.json +63 -0
  148. package/src/cli/index.js +312 -18
  149. package/tokens/banhaten.tokens.json +1 -1
  150. package/registry/assets/avatars/avatar-02.jpg +0 -0
  151. package/registry/assets/avatars/avatar-03.jpg +0 -0
  152. package/registry/assets/avatars/avatar-04.jpg +0 -0
  153. package/registry/assets/avatars/avatar-05.jpg +0 -0
  154. package/registry/assets/avatars/avatar-06.jpg +0 -0
  155. package/registry/assets/avatars/avatar-07.jpg +0 -0
  156. package/registry/assets/avatars/avatar-08.jpg +0 -0
  157. package/registry/assets/avatars/avatar-09.jpg +0 -0
  158. package/registry/assets/avatars/avatar-10.jpg +0 -0
  159. package/registry/assets/avatars/avatar-11.jpg +0 -0
  160. package/registry/assets/avatars/avatar-12.jpg +0 -0
  161. package/registry/assets/avatars/avatar-13.jpg +0 -0
  162. package/registry/assets/avatars/avatar-14.jpg +0 -0
  163. package/registry/assets/avatars/avatar-15.jpg +0 -0
  164. package/registry/assets/avatars/avatar-16.jpg +0 -0
  165. package/registry/assets/avatars/avatar-17.jpg +0 -0
  166. package/registry/assets/avatars/avatar-18.jpg +0 -0
  167. package/registry/assets/avatars/avatar-19.jpg +0 -0
  168. package/registry/assets/avatars/avatar-20.jpg +0 -0
  169. package/registry/assets/avatars/avatar-21.jpg +0 -0
  170. package/registry/assets/avatars/avatar-22.jpg +0 -0
  171. package/registry/assets/avatars/avatar-23.jpg +0 -0
  172. package/registry/assets/avatars/avatar-24.jpg +0 -0
  173. package/registry/assets/avatars/avatar-25.jpg +0 -0
  174. package/registry/assets/avatars/avatar-26.jpg +0 -0
  175. package/registry/assets/avatars/avatar-27.jpg +0 -0
  176. package/registry/assets/avatars/avatar-28.jpg +0 -0
  177. package/registry/assets/avatars/avatar-29.jpg +0 -0
  178. package/registry/assets/avatars/avatar-30.jpg +0 -0
  179. package/registry/assets/avatars/avatar-31.jpg +0 -0
  180. package/registry/assets/avatars/avatar-32.jpg +0 -0
  181. package/registry/assets/avatars/avatar-33.jpg +0 -0
  182. package/registry/assets/avatars/avatar-34.jpg +0 -0
  183. package/registry/assets/avatars/avatar-35.jpg +0 -0
  184. package/registry/assets/image-assets.json +0 -744
  185. package/registry/assets/images/art-02.jpg +0 -0
  186. package/registry/assets/images/art-03.jpg +0 -0
  187. package/registry/assets/images/art-04.jpg +0 -0
  188. package/registry/assets/images/art-05.jpg +0 -0
  189. package/registry/assets/images/art-06.jpg +0 -0
  190. package/registry/assets/images/art-07.jpg +0 -0
  191. package/registry/assets/images/art-08.jpg +0 -0
  192. package/registry/assets/images/art-09.jpg +0 -0
  193. package/registry/assets/images/art-10.jpg +0 -0
  194. package/registry/assets/images/art-11.jpg +0 -0
  195. package/registry/assets/images/art-12.jpg +0 -0
  196. package/registry/assets/images/art-13.jpg +0 -0
  197. package/registry/assets/images/art-14.jpg +0 -0
  198. package/registry/assets/images/art-15.jpg +0 -0
  199. package/registry/assets/images/art-16.jpg +0 -0
  200. package/registry/assets/images/art-17.jpg +0 -0
  201. package/registry/assets/images/art-18.jpg +0 -0
  202. package/registry/assets/images/art-19.jpg +0 -0
  203. package/registry/assets/images/art-20.jpg +0 -0
  204. package/registry/assets/images/art-21.jpg +0 -0
  205. package/registry/assets/images/art-22.jpg +0 -0
  206. package/registry/assets/images/art-23.jpg +0 -0
  207. package/registry/assets/images/art-24.jpg +0 -0
  208. package/registry/assets/images/art-25.jpg +0 -0
  209. package/registry/assets/images/art-26.jpg +0 -0
  210. package/registry/assets/images/art-27.jpg +0 -0
  211. package/registry/assets/images/nature-01.jpg +0 -0
  212. package/registry/assets/images/nature-02.jpg +0 -0
  213. package/registry/assets/images/nature-03.jpg +0 -0
  214. package/registry/assets/images/nature-04.jpg +0 -0
  215. package/registry/assets/images/nature-05.jpg +0 -0
  216. package/registry/assets/images/nature-06.jpg +0 -0
  217. package/registry/assets/images/nature-07.jpg +0 -0
  218. package/registry/assets/images/nature-08.jpg +0 -0
  219. package/registry/assets/images/nature-09.jpg +0 -0
  220. package/registry/assets/images/nature-10.jpg +0 -0
  221. package/registry/assets/images/nature-11.jpg +0 -0
  222. package/registry/assets/images/nature-12.jpg +0 -0
  223. package/registry/assets/images/nature-13.jpg +0 -0
  224. package/registry/assets/images/nature-14.jpg +0 -0
  225. package/registry/assets/images/nature-15.jpg +0 -0
  226. package/registry/assets/images/nature-16.jpg +0 -0
  227. package/registry/assets/images/nature-17.jpg +0 -0
  228. package/registry/assets/images/nature-18.jpg +0 -0
  229. package/registry/assets/images/nature-19.jpg +0 -0
  230. package/registry/assets/images/nature-20.jpg +0 -0
  231. package/registry/components/expanded/Tabs.tsx +0 -86
@@ -0,0 +1,131 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ Toaster as SonnerToaster,
6
+ toast as sonnerToast,
7
+ type ExternalToast,
8
+ type ToasterProps as SonnerToasterProps,
9
+ } from "sonner"
10
+
11
+ import { cn } from "@/lib/utils"
12
+
13
+ type ToastIntent = "default" | "success" | "danger" | "warning" | "info"
14
+ type ToastSide = "start" | "end"
15
+ type ToastOptions = ExternalToast & {
16
+ intent?: ToastIntent
17
+ }
18
+ type ToasterProps = Omit<SonnerToasterProps, "position"> & {
19
+ dir?: "ltr" | "rtl"
20
+ position?: SonnerToasterProps["position"]
21
+ side?: ToastSide
22
+ }
23
+
24
+ const intentClassNames: Record<ToastIntent, string> = {
25
+ danger:
26
+ "[--bh-toast-accent:var(--bh-content-danger-default)] [--bh-toast-accent-bg:var(--bh-bg-danger-subtle)]",
27
+ default:
28
+ "[--bh-toast-accent:var(--bh-content-brand-default)] [--bh-toast-accent-bg:var(--bh-bg-brand-subtle)]",
29
+ info:
30
+ "[--bh-toast-accent:var(--bh-content-brand-default)] [--bh-toast-accent-bg:var(--bh-bg-info-subtle)]",
31
+ success:
32
+ "[--bh-toast-accent:var(--bh-content-success-default)] [--bh-toast-accent-bg:var(--bh-bg-success-subtle)]",
33
+ warning:
34
+ "[--bh-toast-accent:var(--bh-content-warning-default)] [--bh-toast-accent-bg:var(--bh-bg-warning-subtle)]",
35
+ }
36
+
37
+ const toastClassName = [
38
+ "border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)] text-[var(--bh-content-default)] shadow-[var(--shadow-component-default)]",
39
+ "rounded-[var(--bh-radius-xl-10)] font-[var(--bh-font-family)]",
40
+ "[--normal-bg:var(--bh-bg-raised)] [--normal-border:var(--bh-border-subtle)] [--normal-text:var(--bh-content-default)]",
41
+ "[--success-bg:var(--bh-bg-raised)] [--success-border:var(--bh-border-success-subtle)] [--success-text:var(--bh-content-default)]",
42
+ "[--error-bg:var(--bh-bg-raised)] [--error-border:var(--bh-border-danger-subtle)] [--error-text:var(--bh-content-default)]",
43
+ "[--warning-bg:var(--bh-bg-raised)] [--warning-border:var(--bh-border-warning-subtle)] [--warning-text:var(--bh-content-default)]",
44
+ "[--info-bg:var(--bh-bg-raised)] [--info-border:var(--bh-border-info-subtle)] [--info-text:var(--bh-content-default)]",
45
+ ].join(" ")
46
+
47
+ function Toaster({
48
+ className,
49
+ closeButton = true,
50
+ dir,
51
+ position,
52
+ richColors = false,
53
+ side = "end",
54
+ toastOptions,
55
+ ...props
56
+ }: ToasterProps) {
57
+ const resolvedPosition = position ?? getToastPosition(dir, side)
58
+ const mergedToastOptions: ToasterProps["toastOptions"] = {
59
+ ...toastOptions,
60
+ classNames: {
61
+ ...toastOptions?.classNames,
62
+ toast: cn(toastClassName, toastOptions?.classNames?.toast),
63
+ title: cn(
64
+ "text-[length:var(--bh-text-body-sm-semibold-font-size)] font-[var(--bh-text-body-sm-semibold-font-weight)] leading-[var(--bh-text-body-sm-semibold-line-height)] tracking-[var(--bh-text-body-sm-semibold-letter-spacing)]",
65
+ toastOptions?.classNames?.title
66
+ ),
67
+ description: cn(
68
+ "text-[length:var(--bh-text-body-xs-regular-font-size)] font-[var(--bh-text-body-xs-regular-font-weight)] leading-[var(--bh-text-body-xs-regular-line-height)] tracking-[var(--bh-text-body-xs-regular-letter-spacing)] text-[var(--bh-content-subtle)]",
69
+ toastOptions?.classNames?.description
70
+ ),
71
+ actionButton: cn(
72
+ "rounded-[var(--bh-control-default)] bg-[var(--bh-interactive-primary-default)] px-[var(--bh-space-lg-10)] py-[var(--bh-space-xs-4)] text-[var(--bh-content-on-color)]",
73
+ toastOptions?.classNames?.actionButton
74
+ ),
75
+ cancelButton: cn(
76
+ "rounded-[var(--bh-control-default)] bg-[var(--bh-bg-neutral-soft)] px-[var(--bh-space-lg-10)] py-[var(--bh-space-xs-4)] text-[var(--bh-content-default)]",
77
+ toastOptions?.classNames?.cancelButton
78
+ ),
79
+ },
80
+ }
81
+
82
+ return (
83
+ <SonnerToaster
84
+ className={cn("toaster group", className)}
85
+ closeButton={closeButton}
86
+ dir={dir}
87
+ position={resolvedPosition}
88
+ richColors={richColors}
89
+ toastOptions={mergedToastOptions}
90
+ {...props}
91
+ />
92
+ )
93
+ }
94
+
95
+ function showToast(message: React.ReactNode, options: ToastOptions = {}) {
96
+ const { intent = "default", className, ...rest } = options
97
+ return sonnerToast(message, {
98
+ className: cn(intentClassNames[intent], className),
99
+ ...rest,
100
+ })
101
+ }
102
+
103
+ const toast = Object.assign(showToast, {
104
+ danger: (message: React.ReactNode, options?: Omit<ToastOptions, "intent">) =>
105
+ showToast(message, { ...options, intent: "danger" }),
106
+ dismiss: sonnerToast.dismiss,
107
+ error: (message: React.ReactNode, options?: Omit<ToastOptions, "intent">) =>
108
+ showToast(message, { ...options, intent: "danger" }),
109
+ info: (message: React.ReactNode, options?: Omit<ToastOptions, "intent">) =>
110
+ showToast(message, { ...options, intent: "info" }),
111
+ loading: sonnerToast.loading,
112
+ promise: sonnerToast.promise,
113
+ success: (message: React.ReactNode, options?: Omit<ToastOptions, "intent">) =>
114
+ showToast(message, { ...options, intent: "success" }),
115
+ warning: (message: React.ReactNode, options?: Omit<ToastOptions, "intent">) =>
116
+ showToast(message, { ...options, intent: "warning" }),
117
+ })
118
+
119
+ function getToastPosition(
120
+ dir: ToasterProps["dir"],
121
+ side: ToastSide
122
+ ): SonnerToasterProps["position"] {
123
+ if (side === "start") {
124
+ return dir === "rtl" ? "top-right" : "top-left"
125
+ }
126
+
127
+ return dir === "rtl" ? "top-left" : "top-right"
128
+ }
129
+
130
+ export { Toaster, toast }
131
+ export type { ToastIntent, ToastOptions, ToasterProps }
@@ -0,0 +1,42 @@
1
+ import { Button } from "@/components/ui/button"
2
+ import {
3
+ AlertDialog,
4
+ AlertDialogAction,
5
+ AlertDialogBody,
6
+ AlertDialogCancel,
7
+ AlertDialogContent,
8
+ AlertDialogDescription,
9
+ AlertDialogFooter,
10
+ AlertDialogHeader,
11
+ AlertDialogIcon,
12
+ AlertDialogTitle,
13
+ AlertDialogTrigger,
14
+ } from "@/components/ui/alert-dialog"
15
+
16
+ export function AlertDialogDemo() {
17
+ return (
18
+ <AlertDialog>
19
+ <AlertDialogTrigger asChild>
20
+ <Button size="sm" variant="danger">
21
+ Delete project
22
+ </Button>
23
+ </AlertDialogTrigger>
24
+ <AlertDialogContent>
25
+ <AlertDialogHeader>
26
+ <AlertDialogIcon intent="danger" />
27
+ <AlertDialogTitle>Delete project?</AlertDialogTitle>
28
+ </AlertDialogHeader>
29
+ <AlertDialogBody>
30
+ <AlertDialogDescription>
31
+ This action cannot be undone. All environments, deployments, and
32
+ saved settings will be permanently removed.
33
+ </AlertDialogDescription>
34
+ </AlertDialogBody>
35
+ <AlertDialogFooter>
36
+ <AlertDialogCancel>Cancel</AlertDialogCancel>
37
+ <AlertDialogAction>Delete project</AlertDialogAction>
38
+ </AlertDialogFooter>
39
+ </AlertDialogContent>
40
+ </AlertDialog>
41
+ )
42
+ }
@@ -0,0 +1,11 @@
1
+ import { AspectRatio } from "@/components/ui/aspect-ratio"
2
+
3
+ export function AspectRatioDemo() {
4
+ return (
5
+ <AspectRatio ratio={16 / 9} className="max-w-xl">
6
+ <div className="flex size-full items-center justify-center bg-[var(--bh-bg-neutral-subtle)] text-[var(--bh-content-subtle)]">
7
+ 16:9
8
+ </div>
9
+ </AspectRatio>
10
+ )
11
+ }
@@ -0,0 +1,25 @@
1
+ import {
2
+ Carousel,
3
+ CarouselContent,
4
+ CarouselItem,
5
+ CarouselNext,
6
+ CarouselPrevious,
7
+ } from "@/components/ui/carousel"
8
+
9
+ export function CarouselDemo() {
10
+ return (
11
+ <Carousel className="w-full max-w-sm">
12
+ <CarouselContent>
13
+ {[1, 2, 3].map((item) => (
14
+ <CarouselItem key={item}>
15
+ <div className="flex aspect-video items-center justify-center rounded-xl bg-[var(--bh-bg-neutral-subtle)] text-lg font-semibold">
16
+ {item}
17
+ </div>
18
+ </CarouselItem>
19
+ ))}
20
+ </CarouselContent>
21
+ <CarouselPrevious />
22
+ <CarouselNext />
23
+ </Carousel>
24
+ )
25
+ }
@@ -0,0 +1,33 @@
1
+ import { Line, LineChart, XAxis, YAxis } from "recharts"
2
+
3
+ import {
4
+ ChartContainer,
5
+ ChartTooltip,
6
+ ChartTooltipContent,
7
+ } from "@/components/ui/chart"
8
+
9
+ const data = [
10
+ { month: "Jan", revenue: 120 },
11
+ { month: "Feb", revenue: 180 },
12
+ { month: "Mar", revenue: 150 },
13
+ { month: "Apr", revenue: 220 },
14
+ ]
15
+
16
+ export function ChartDemo() {
17
+ return (
18
+ <ChartContainer config={{ revenue: { color: "var(--bh-chart-1)" } }}>
19
+ <LineChart data={data}>
20
+ <XAxis dataKey="month" tickLine={false} axisLine={false} />
21
+ <YAxis tickLine={false} axisLine={false} width={32} />
22
+ <ChartTooltip content={<ChartTooltipContent />} />
23
+ <Line
24
+ dataKey="revenue"
25
+ type="monotone"
26
+ stroke="var(--color-revenue)"
27
+ strokeWidth={2}
28
+ dot={false}
29
+ />
30
+ </LineChart>
31
+ </ChartContainer>
32
+ )
33
+ }
@@ -0,0 +1,16 @@
1
+ import {
2
+ Collapsible,
3
+ CollapsibleContent,
4
+ CollapsibleTrigger,
5
+ } from "@/components/ui/collapsible"
6
+
7
+ export function CollapsibleDemo() {
8
+ return (
9
+ <Collapsible defaultOpen className="w-full max-w-md rounded-xl border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)]">
10
+ <CollapsibleTrigger>Workspace details</CollapsibleTrigger>
11
+ <CollapsibleContent>
12
+ Billing, members, and audit controls are grouped in this section.
13
+ </CollapsibleContent>
14
+ </Collapsible>
15
+ )
16
+ }
@@ -0,0 +1,42 @@
1
+ import { FileTextIcon, SettingsIcon, UserIcon } from "lucide-react"
2
+
3
+ import {
4
+ Command,
5
+ CommandEmpty,
6
+ CommandGroup,
7
+ CommandInput,
8
+ CommandItem,
9
+ CommandList,
10
+ CommandSeparator,
11
+ CommandShortcut,
12
+ } from "@/components/ui/command"
13
+
14
+ export function CommandDemo() {
15
+ return (
16
+ <Command>
17
+ <CommandInput />
18
+ <CommandList>
19
+ <CommandEmpty>No results found.</CommandEmpty>
20
+ <CommandGroup heading="Pages">
21
+ <CommandItem value="profile">
22
+ <UserIcon className="size-4" />
23
+ Profile
24
+ <CommandShortcut>⌘P</CommandShortcut>
25
+ </CommandItem>
26
+ <CommandItem value="docs">
27
+ <FileTextIcon className="size-4" />
28
+ Docs
29
+ <CommandShortcut>⌘D</CommandShortcut>
30
+ </CommandItem>
31
+ </CommandGroup>
32
+ <CommandSeparator />
33
+ <CommandGroup heading="Actions">
34
+ <CommandItem value="settings">
35
+ <SettingsIcon className="size-4" />
36
+ Settings
37
+ </CommandItem>
38
+ </CommandGroup>
39
+ </CommandList>
40
+ </Command>
41
+ )
42
+ }
@@ -0,0 +1,29 @@
1
+ import {
2
+ ContextMenu,
3
+ ContextMenuContent,
4
+ ContextMenuItem,
5
+ ContextMenuLabel,
6
+ ContextMenuSeparator,
7
+ ContextMenuShortcut,
8
+ ContextMenuTrigger,
9
+ } from "@/components/ui/context-menu"
10
+
11
+ export function ContextMenuDemo() {
12
+ return (
13
+ <ContextMenu>
14
+ <ContextMenuTrigger className="flex h-32 w-64 items-center justify-center rounded-xl border border-dashed border-[var(--bh-border-default)] text-sm">
15
+ Right click
16
+ </ContextMenuTrigger>
17
+ <ContextMenuContent>
18
+ <ContextMenuLabel>Project</ContextMenuLabel>
19
+ <ContextMenuItem>
20
+ Open
21
+ <ContextMenuShortcut>⌘O</ContextMenuShortcut>
22
+ </ContextMenuItem>
23
+ <ContextMenuItem>Duplicate</ContextMenuItem>
24
+ <ContextMenuSeparator />
25
+ <ContextMenuItem>Archive</ContextMenuItem>
26
+ </ContextMenuContent>
27
+ </ContextMenu>
28
+ )
29
+ }
@@ -1,4 +1,4 @@
1
- import { Tabs } from "@/components/ui/expanded/Tabs"
1
+ import { Tabs } from "@/components/ui/tabs"
2
2
 
3
3
  const tabItems = ["Overview", "Details", "Settings", "Activity", "Files"]
4
4
 
@@ -0,0 +1,51 @@
1
+ import { Button } from "@/components/ui/button"
2
+ import {
3
+ Field,
4
+ FieldContent,
5
+ FieldControl,
6
+ FieldDescription,
7
+ FieldError,
8
+ FieldGroup,
9
+ FieldLabel,
10
+ FieldLegend,
11
+ FieldSet,
12
+ } from "@/components/ui/field"
13
+ import { Input } from "@/components/ui/input"
14
+ import { Textarea } from "@/components/ui/textarea"
15
+
16
+ export function FieldDemo() {
17
+ return (
18
+ <FieldSet>
19
+ <FieldLegend>Account details</FieldLegend>
20
+ <FieldGroup>
21
+ <Field>
22
+ <FieldLabel>Email</FieldLabel>
23
+ <FieldControl>
24
+ <Input placeholder="name@example.com" />
25
+ </FieldControl>
26
+ <FieldDescription>Use your work email for team access.</FieldDescription>
27
+ </Field>
28
+
29
+ <Field invalid>
30
+ <FieldLabel>Workspace</FieldLabel>
31
+ <FieldControl>
32
+ <Input state="error" valueText="Banhaten" />
33
+ </FieldControl>
34
+ <FieldError>Workspace name is already taken.</FieldError>
35
+ </Field>
36
+
37
+ <Field orientation="responsive">
38
+ <FieldContent>
39
+ <FieldLabel>Notes</FieldLabel>
40
+ <FieldDescription>Visible to workspace administrators.</FieldDescription>
41
+ </FieldContent>
42
+ <FieldControl>
43
+ <Textarea placeholder="Add setup notes..." />
44
+ </FieldControl>
45
+ </Field>
46
+
47
+ <Button size="sm">Save details</Button>
48
+ </FieldGroup>
49
+ </FieldSet>
50
+ )
51
+ }
@@ -0,0 +1,23 @@
1
+ import {
2
+ HoverCard,
3
+ HoverCardContent,
4
+ HoverCardTrigger,
5
+ } from "@/components/ui/hover-card"
6
+
7
+ export function HoverCardDemo() {
8
+ return (
9
+ <HoverCard>
10
+ <HoverCardTrigger className="underline underline-offset-4">
11
+ Workspace profile
12
+ </HoverCardTrigger>
13
+ <HoverCardContent>
14
+ <div className="grid gap-1">
15
+ <strong>Design System</strong>
16
+ <span className="text-sm text-[var(--bh-content-subtle)]">
17
+ Tokens, components, and RTL-ready examples.
18
+ </span>
19
+ </div>
20
+ </HoverCardContent>
21
+ </HoverCard>
22
+ )
23
+ }
@@ -0,0 +1,16 @@
1
+ import {
2
+ InputGroup,
3
+ InputGroupAddon,
4
+ InputGroupButton,
5
+ InputGroupInput,
6
+ } from "@/components/ui/input-group"
7
+
8
+ export function InputGroupDemo() {
9
+ return (
10
+ <InputGroup>
11
+ <InputGroupAddon>https://</InputGroupAddon>
12
+ <InputGroupInput aria-label="Workspace URL" defaultValue="banhaten.design" />
13
+ <InputGroupButton>Save</InputGroupButton>
14
+ </InputGroup>
15
+ )
16
+ }
@@ -0,0 +1,11 @@
1
+ import { Kbd } from "@/components/ui/kbd"
2
+
3
+ export function KbdDemo() {
4
+ return (
5
+ <div className="flex flex-wrap items-center gap-2">
6
+ <Kbd>⌘</Kbd>
7
+ <Kbd>K</Kbd>
8
+ <Kbd size="md">Shift</Kbd>
9
+ </div>
10
+ )
11
+ }
@@ -0,0 +1,20 @@
1
+ import { Checkbox } from "@/components/ui/checkbox"
2
+ import { Label } from "@/components/ui/label"
3
+
4
+ export function LabelDemo() {
5
+ return (
6
+ <div className="grid gap-4">
7
+ <div className="flex items-center gap-[var(--bh-space-md-8)]">
8
+ <Checkbox id="terms" />
9
+ <Label htmlFor="terms">Accept terms and conditions</Label>
10
+ </div>
11
+ <Label optionalText="(Optional)">Project name</Label>
12
+ <div dir="rtl" className="flex items-center gap-[var(--bh-space-md-8)]">
13
+ <Checkbox id="terms-rtl" />
14
+ <Label htmlFor="terms-rtl" required>
15
+ قبول الشروط والأحكام
16
+ </Label>
17
+ </div>
18
+ </div>
19
+ )
20
+ }
@@ -0,0 +1,34 @@
1
+ import {
2
+ Menubar,
3
+ MenubarContent,
4
+ MenubarItem,
5
+ MenubarMenu,
6
+ MenubarSeparator,
7
+ MenubarShortcut,
8
+ MenubarTrigger,
9
+ } from "@/components/ui/menubar"
10
+
11
+ export function MenubarDemo() {
12
+ return (
13
+ <Menubar>
14
+ <MenubarMenu>
15
+ <MenubarTrigger>File</MenubarTrigger>
16
+ <MenubarContent>
17
+ <MenubarItem>
18
+ New
19
+ <MenubarShortcut>⌘N</MenubarShortcut>
20
+ </MenubarItem>
21
+ <MenubarItem>Open</MenubarItem>
22
+ <MenubarSeparator />
23
+ <MenubarItem>Export</MenubarItem>
24
+ </MenubarContent>
25
+ </MenubarMenu>
26
+ <MenubarMenu>
27
+ <MenubarTrigger>View</MenubarTrigger>
28
+ <MenubarContent>
29
+ <MenubarItem>Toggle sidebar</MenubarItem>
30
+ </MenubarContent>
31
+ </MenubarMenu>
32
+ </Menubar>
33
+ )
34
+ }
@@ -0,0 +1,16 @@
1
+ import { NativeSelect } from "@/components/ui/native-select"
2
+
3
+ export function NativeSelectDemo() {
4
+ return (
5
+ <NativeSelect
6
+ label="Workspace"
7
+ defaultValue="design"
8
+ helperText="Native select for platform forms."
9
+ options={[
10
+ { label: "Design", value: "design" },
11
+ { label: "Engineering", value: "engineering" },
12
+ { label: "Operations", value: "operations" },
13
+ ]}
14
+ />
15
+ )
16
+ }
@@ -0,0 +1,29 @@
1
+ import {
2
+ NavigationMenu,
3
+ NavigationMenuContent,
4
+ NavigationMenuItem,
5
+ NavigationMenuLink,
6
+ NavigationMenuList,
7
+ NavigationMenuTrigger,
8
+ NavigationMenuViewport,
9
+ } from "@/components/ui/navigation-menu"
10
+
11
+ export function NavigationMenuDemo() {
12
+ return (
13
+ <NavigationMenu>
14
+ <NavigationMenuList>
15
+ <NavigationMenuItem>
16
+ <NavigationMenuTrigger>Product</NavigationMenuTrigger>
17
+ <NavigationMenuContent>
18
+ <div className="grid gap-2">
19
+ <NavigationMenuLink href="#">Components</NavigationMenuLink>
20
+ <NavigationMenuLink href="#">Tokens</NavigationMenuLink>
21
+ <NavigationMenuLink href="#">Patterns</NavigationMenuLink>
22
+ </div>
23
+ </NavigationMenuContent>
24
+ </NavigationMenuItem>
25
+ </NavigationMenuList>
26
+ <NavigationMenuViewport />
27
+ </NavigationMenu>
28
+ )
29
+ }
@@ -0,0 +1,22 @@
1
+ import {
2
+ ResizableHandle,
3
+ ResizablePanel,
4
+ ResizablePanelGroup,
5
+ } from "@/components/ui/resizable"
6
+
7
+ export function ResizableDemo() {
8
+ return (
9
+ <ResizablePanelGroup
10
+ direction="horizontal"
11
+ className="h-48 rounded-xl border border-[var(--bh-border-subtle)]"
12
+ >
13
+ <ResizablePanel defaultSize={35}>
14
+ <div className="flex size-full items-center justify-center text-sm">Sidebar</div>
15
+ </ResizablePanel>
16
+ <ResizableHandle withHandle />
17
+ <ResizablePanel defaultSize={65}>
18
+ <div className="flex size-full items-center justify-center text-sm">Content</div>
19
+ </ResizablePanel>
20
+ </ResizablePanelGroup>
21
+ )
22
+ }
@@ -0,0 +1,15 @@
1
+ import { ScrollArea } from "@/components/ui/scroll-area"
2
+
3
+ export function ScrollAreaDemo() {
4
+ return (
5
+ <ScrollArea className="h-48 w-72 rounded-xl border border-[var(--bh-border-subtle)] bg-[var(--bh-bg-raised)]">
6
+ <div className="grid gap-2 p-4">
7
+ {Array.from({ length: 12 }, (_, index) => (
8
+ <div key={index} className="rounded-lg bg-[var(--bh-bg-neutral-subtle)] px-3 py-2 text-sm">
9
+ Activity item {index + 1}
10
+ </div>
11
+ ))}
12
+ </div>
13
+ </ScrollArea>
14
+ )
15
+ }
@@ -0,0 +1,47 @@
1
+ import { Button } from "@/components/ui/button"
2
+ import {
3
+ Sheet,
4
+ SheetBody,
5
+ SheetContent,
6
+ SheetDescription,
7
+ SheetFooter,
8
+ SheetHeader,
9
+ SheetTitle,
10
+ SheetTrigger,
11
+ } from "@/components/ui/sheet"
12
+
13
+ export function SheetDemo() {
14
+ return (
15
+ <div className="flex flex-wrap gap-[var(--bh-space-md-8)]">
16
+ {(["start", "end", "top", "bottom"] as const).map((side) => (
17
+ <Sheet key={side}>
18
+ <SheetTrigger asChild>
19
+ <Button size="sm" variant="outline">
20
+ {side}
21
+ </Button>
22
+ </SheetTrigger>
23
+ <SheetContent side={side}>
24
+ <SheetHeader>
25
+ <SheetTitle>Workspace settings</SheetTitle>
26
+ <SheetDescription>
27
+ Review billing, access, and notification settings.
28
+ </SheetDescription>
29
+ </SheetHeader>
30
+ <SheetBody>
31
+ <div className="grid gap-[var(--bh-space-md-8)] text-[length:var(--bh-text-body-sm-regular-font-size)] font-[var(--bh-text-body-sm-regular-font-weight)] leading-[var(--bh-text-body-sm-regular-line-height)] tracking-[var(--bh-text-body-sm-regular-letter-spacing)] text-[var(--bh-content-subtle)]">
32
+ <p>Sheets are suited to contextual workflows that need more space than a popover.</p>
33
+ <p>Use logical start and end sides so the panel mirrors in RTL surfaces.</p>
34
+ </div>
35
+ </SheetBody>
36
+ <SheetFooter>
37
+ <Button size="sm" variant="soft">
38
+ Cancel
39
+ </Button>
40
+ <Button size="sm">Save changes</Button>
41
+ </SheetFooter>
42
+ </SheetContent>
43
+ </Sheet>
44
+ ))}
45
+ </div>
46
+ )
47
+ }