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,305 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog"
5
+ import { cva, type VariantProps } from "class-variance-authority"
6
+ import { XIcon } from "lucide-react"
7
+
8
+ import { cn } from "@/lib/utils"
9
+
10
+ type SheetSide = "start" | "end" | "top" | "bottom"
11
+ type SheetSize = "sm" | "default" | "lg"
12
+
13
+ const sheetContentVariants = cva(
14
+ [
15
+ "fixed z-[var(--bh-z-overlay)] flex flex-col overflow-hidden bg-[var(--bh-bg-raised)] text-[var(--bh-content-default)]",
16
+ "shadow-[var(--shadow-component-default)] outline-none",
17
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
18
+ ],
19
+ {
20
+ variants: {
21
+ side: {
22
+ bottom:
23
+ "inset-x-0 bottom-0 max-h-[calc(100vh-var(--bh-space-8xl-48))] rounded-t-[var(--bh-radius-2xl-12)] border-t border-[var(--bh-border-subtle)] data-[state=open]:slide-in-from-bottom data-[state=closed]:slide-out-to-bottom",
24
+ end:
25
+ "inset-y-0 end-0 h-full max-w-[calc(100vw-var(--bh-space-4xl-20))] border-s border-[var(--bh-border-subtle)] data-[state=open]:slide-in-from-right data-[state=closed]:slide-out-to-right rtl:data-[state=open]:slide-in-from-left rtl:data-[state=closed]:slide-out-to-left",
26
+ start:
27
+ "inset-y-0 start-0 h-full max-w-[calc(100vw-var(--bh-space-4xl-20))] border-e border-[var(--bh-border-subtle)] data-[state=open]:slide-in-from-left data-[state=closed]:slide-out-to-left rtl:data-[state=open]:slide-in-from-right rtl:data-[state=closed]:slide-out-to-right",
28
+ top:
29
+ "inset-x-0 top-0 max-h-[calc(100vh-var(--bh-space-8xl-48))] rounded-b-[var(--bh-radius-2xl-12)] border-b border-[var(--bh-border-subtle)] data-[state=open]:slide-in-from-top data-[state=closed]:slide-out-to-top",
30
+ },
31
+ size: {
32
+ default: "",
33
+ lg: "",
34
+ sm: "",
35
+ },
36
+ },
37
+ compoundVariants: [
38
+ {
39
+ side: ["start", "end"],
40
+ size: "sm",
41
+ className:
42
+ "w-[min(var(--bh-space-19xl-384),calc(100vw-var(--bh-space-4xl-20)))]",
43
+ },
44
+ {
45
+ side: ["start", "end"],
46
+ size: "default",
47
+ className:
48
+ "w-[min(calc(var(--bh-space-19xl-384)+var(--bh-space-9xl-64)),calc(100vw-var(--bh-space-4xl-20)))]",
49
+ },
50
+ {
51
+ side: ["start", "end"],
52
+ size: "lg",
53
+ className:
54
+ "w-[min(calc(var(--bh-space-19xl-384)+var(--bh-space-12xl-128)),calc(100vw-var(--bh-space-4xl-20)))]",
55
+ },
56
+ {
57
+ side: ["top", "bottom"],
58
+ size: "sm",
59
+ className: "min-h-[var(--bh-space-12xl-128)]",
60
+ },
61
+ {
62
+ side: ["top", "bottom"],
63
+ size: "default",
64
+ className: "min-h-[var(--bh-space-16xl-256)]",
65
+ },
66
+ {
67
+ side: ["top", "bottom"],
68
+ size: "lg",
69
+ className: "min-h-[var(--bh-space-17xl-288)]",
70
+ },
71
+ ],
72
+ defaultVariants: {
73
+ side: "end",
74
+ size: "default",
75
+ },
76
+ }
77
+ )
78
+
79
+ type SheetRootProps = React.ComponentProps<typeof DialogPrimitive.Root>
80
+ type SheetTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>
81
+ type SheetCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>
82
+ type SheetPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>
83
+ type SheetOverlayProps = React.ComponentPropsWithoutRef<
84
+ typeof DialogPrimitive.Overlay
85
+ >
86
+ type SheetContentProps = React.ComponentPropsWithoutRef<
87
+ typeof DialogPrimitive.Content
88
+ > &
89
+ VariantProps<typeof sheetContentVariants> & {
90
+ overlayClassName?: string
91
+ showCloseButton?: boolean
92
+ }
93
+ type SheetHeaderProps = React.ComponentProps<"header">
94
+ type SheetFooterProps = React.ComponentProps<"footer">
95
+ type SheetBodyProps = React.ComponentProps<"div">
96
+ type SheetTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
97
+ type SheetDescriptionProps = React.ComponentPropsWithoutRef<
98
+ typeof DialogPrimitive.Description
99
+ >
100
+ type SheetCloseButtonProps = React.ComponentProps<"button"> & {
101
+ label?: string
102
+ }
103
+
104
+ const Sheet = DialogPrimitive.Root
105
+ const SheetTrigger = DialogPrimitive.Trigger
106
+ const SheetClose = DialogPrimitive.Close
107
+ const SheetPortal = DialogPrimitive.Portal
108
+
109
+ const SheetOverlay = React.forwardRef<
110
+ React.ElementRef<typeof DialogPrimitive.Overlay>,
111
+ SheetOverlayProps
112
+ >(function SheetOverlay({ className, ...props }, ref) {
113
+ return (
114
+ <DialogPrimitive.Overlay
115
+ data-slot="sheet-overlay"
116
+ ref={ref}
117
+ className={cn(
118
+ "fixed inset-0 z-[var(--bh-z-overlay)] bg-[var(--bh-bg-backdrop)]",
119
+ className
120
+ )}
121
+ {...props}
122
+ />
123
+ )
124
+ })
125
+
126
+ const SheetContent = React.forwardRef<
127
+ React.ElementRef<typeof DialogPrimitive.Content>,
128
+ SheetContentProps
129
+ >(function SheetContent(
130
+ {
131
+ children,
132
+ className,
133
+ overlayClassName,
134
+ showCloseButton = true,
135
+ side = "end",
136
+ size = "default",
137
+ ...props
138
+ },
139
+ ref
140
+ ) {
141
+ return (
142
+ <SheetPortal>
143
+ <SheetOverlay className={overlayClassName} />
144
+ <DialogPrimitive.Content
145
+ data-side={side}
146
+ data-size={size}
147
+ data-slot="sheet-content"
148
+ ref={ref}
149
+ className={cn(sheetContentVariants({ side, size, className }))}
150
+ {...props}
151
+ >
152
+ {children}
153
+ {showCloseButton ? <SheetCloseButton /> : null}
154
+ </DialogPrimitive.Content>
155
+ </SheetPortal>
156
+ )
157
+ })
158
+
159
+ const SheetHeader = React.forwardRef<HTMLElement, SheetHeaderProps>(
160
+ function SheetHeader({ className, ...props }, ref) {
161
+ return (
162
+ <header
163
+ data-slot="sheet-header"
164
+ ref={ref}
165
+ className={cn(
166
+ "grid gap-[var(--bh-space-xs-4)] px-[var(--bh-space-4xl-20)] pb-[var(--bh-space-lg-10)] pe-[var(--bh-space-9xl-64)] pt-[var(--bh-space-4xl-20)] text-start",
167
+ className
168
+ )}
169
+ {...props}
170
+ />
171
+ )
172
+ }
173
+ )
174
+
175
+ const SheetBody = React.forwardRef<HTMLDivElement, SheetBodyProps>(
176
+ function SheetBody({ className, ...props }, ref) {
177
+ return (
178
+ <div
179
+ data-slot="sheet-body"
180
+ ref={ref}
181
+ className={cn(
182
+ "min-h-0 flex-1 overflow-auto px-[var(--bh-space-4xl-20)] py-[var(--bh-space-lg-10)] text-start",
183
+ className
184
+ )}
185
+ {...props}
186
+ />
187
+ )
188
+ }
189
+ )
190
+
191
+ const SheetFooter = React.forwardRef<HTMLElement, SheetFooterProps>(
192
+ function SheetFooter({ className, ...props }, ref) {
193
+ return (
194
+ <footer
195
+ data-slot="sheet-footer"
196
+ ref={ref}
197
+ className={cn(
198
+ "flex shrink-0 flex-wrap items-center justify-end gap-[var(--bh-space-md-8)] border-t border-[var(--bh-border-subtle)] px-[var(--bh-space-4xl-20)] py-[var(--bh-space-3xl-16)]",
199
+ className
200
+ )}
201
+ {...props}
202
+ />
203
+ )
204
+ }
205
+ )
206
+
207
+ const SheetTitle = React.forwardRef<
208
+ React.ElementRef<typeof DialogPrimitive.Title>,
209
+ SheetTitleProps
210
+ >(function SheetTitle({ className, dir = "auto", ...props }, ref) {
211
+ return (
212
+ <DialogPrimitive.Title
213
+ data-slot="sheet-title"
214
+ dir={dir}
215
+ ref={ref}
216
+ className={cn(
217
+ "m-0 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)]",
218
+ className
219
+ )}
220
+ {...props}
221
+ />
222
+ )
223
+ })
224
+
225
+ const SheetDescription = React.forwardRef<
226
+ React.ElementRef<typeof DialogPrimitive.Description>,
227
+ SheetDescriptionProps
228
+ >(function SheetDescription({ className, dir = "auto", ...props }, ref) {
229
+ return (
230
+ <DialogPrimitive.Description
231
+ data-slot="sheet-description"
232
+ dir={dir}
233
+ ref={ref}
234
+ className={cn(
235
+ "m-0 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)]",
236
+ className
237
+ )}
238
+ {...props}
239
+ />
240
+ )
241
+ })
242
+
243
+ const SheetCloseButton = React.forwardRef<
244
+ HTMLButtonElement,
245
+ SheetCloseButtonProps
246
+ >(function SheetCloseButton(
247
+ { children, className, label = "Close sheet", type = "button", ...props },
248
+ ref
249
+ ) {
250
+ return (
251
+ <SheetClose asChild>
252
+ <button
253
+ aria-label={label}
254
+ data-slot="sheet-close"
255
+ ref={ref}
256
+ type={type}
257
+ className={cn(
258
+ "absolute end-[var(--bh-space-3xl-16)] top-[var(--bh-space-3xl-16)] inline-flex size-[var(--bh-space-6xl-32)] items-center justify-center rounded-[var(--bh-radius-full)] border-0 bg-transparent p-0 text-[var(--bh-content-subtle)] outline-none transition-[background-color,box-shadow,color] hover:bg-[var(--bh-interactive-ghost-hover)] hover:text-[var(--bh-content-default)] focus-visible:shadow-[var(--shadow-button-focus)]",
259
+ className
260
+ )}
261
+ {...props}
262
+ >
263
+ {children ?? (
264
+ <XIcon
265
+ aria-hidden="true"
266
+ className="size-[var(--bh-space-5xl-24)]"
267
+ strokeWidth={2}
268
+ />
269
+ )}
270
+ </button>
271
+ </SheetClose>
272
+ )
273
+ })
274
+
275
+ export {
276
+ Sheet,
277
+ SheetBody,
278
+ SheetClose,
279
+ SheetCloseButton,
280
+ SheetContent,
281
+ SheetDescription,
282
+ SheetFooter,
283
+ SheetHeader,
284
+ SheetOverlay,
285
+ SheetPortal,
286
+ SheetTitle,
287
+ SheetTrigger,
288
+ sheetContentVariants,
289
+ }
290
+ export type {
291
+ SheetBodyProps,
292
+ SheetCloseButtonProps,
293
+ SheetCloseProps,
294
+ SheetContentProps,
295
+ SheetDescriptionProps,
296
+ SheetFooterProps,
297
+ SheetHeaderProps,
298
+ SheetOverlayProps,
299
+ SheetPortalProps,
300
+ SheetRootProps,
301
+ SheetSide,
302
+ SheetSize,
303
+ SheetTitleProps,
304
+ SheetTriggerProps,
305
+ }
@@ -0,0 +1,352 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Slot } from "@radix-ui/react-slot"
5
+ import { PanelLeftIcon } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ type SidebarContextValue = {
10
+ collapsed: boolean
11
+ dir?: "ltr" | "rtl"
12
+ setCollapsed: (collapsed: boolean) => void
13
+ toggle: () => void
14
+ }
15
+
16
+ type SidebarProviderProps = React.ComponentProps<"div"> & {
17
+ collapsed?: boolean
18
+ defaultCollapsed?: boolean
19
+ dir?: "ltr" | "rtl"
20
+ onCollapsedChange?: (collapsed: boolean) => void
21
+ }
22
+ type SidebarProps = React.ComponentProps<"aside"> & {
23
+ side?: "start" | "end"
24
+ }
25
+ type SidebarSectionProps = React.ComponentProps<"div">
26
+ type SidebarGroupLabelProps = React.ComponentProps<"div">
27
+ type SidebarMenuProps = React.ComponentProps<"ul">
28
+ type SidebarMenuItemProps = React.ComponentProps<"li">
29
+ type SidebarMenuButtonProps = React.ComponentProps<"button"> & {
30
+ active?: boolean
31
+ asChild?: boolean
32
+ icon?: React.ReactNode
33
+ }
34
+ type SidebarToggleProps = React.ComponentProps<"button">
35
+ type SidebarTriggerProps = SidebarToggleProps
36
+ type SidebarRailProps = React.ComponentProps<"button">
37
+ type SidebarInsetProps = React.ComponentProps<"main">
38
+
39
+ const SidebarContext = React.createContext<SidebarContextValue | null>(null)
40
+
41
+ function SidebarProvider({
42
+ children,
43
+ className,
44
+ collapsed,
45
+ defaultCollapsed = false,
46
+ dir,
47
+ onCollapsedChange,
48
+ ...props
49
+ }: SidebarProviderProps) {
50
+ const [uncontrolledCollapsed, setUncontrolledCollapsed] =
51
+ React.useState(defaultCollapsed)
52
+ const isControlled = collapsed !== undefined
53
+ const resolvedCollapsed = collapsed ?? uncontrolledCollapsed
54
+
55
+ const setCollapsed = React.useCallback(
56
+ (nextCollapsed: boolean) => {
57
+ if (!isControlled) {
58
+ setUncontrolledCollapsed(nextCollapsed)
59
+ }
60
+ onCollapsedChange?.(nextCollapsed)
61
+ },
62
+ [isControlled, onCollapsedChange]
63
+ )
64
+
65
+ const context = React.useMemo<SidebarContextValue>(
66
+ () => ({
67
+ collapsed: resolvedCollapsed,
68
+ dir,
69
+ setCollapsed,
70
+ toggle: () => setCollapsed(!resolvedCollapsed),
71
+ }),
72
+ [dir, resolvedCollapsed, setCollapsed]
73
+ )
74
+
75
+ return (
76
+ <SidebarContext.Provider value={context}>
77
+ <div
78
+ data-collapsed={resolvedCollapsed ? "true" : undefined}
79
+ data-slot="sidebar-provider"
80
+ dir={dir}
81
+ className={cn("min-w-0", className)}
82
+ {...props}
83
+ >
84
+ {children}
85
+ </div>
86
+ </SidebarContext.Provider>
87
+ )
88
+ }
89
+
90
+ const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(function Sidebar(
91
+ { className, side = "start", ...props },
92
+ ref
93
+ ) {
94
+ const { collapsed, dir } = useSidebarContext()
95
+
96
+ return (
97
+ <aside
98
+ data-collapsed={collapsed ? "true" : undefined}
99
+ data-side={side}
100
+ data-slot="sidebar"
101
+ dir={dir}
102
+ ref={ref}
103
+ className={cn(
104
+ "group/sidebar flex h-full min-h-[var(--bh-space-19xl-384)] w-[var(--bh-sidebar-width)] max-w-full shrink-0 flex-col overflow-hidden bg-[var(--bh-sidebar-bg)] text-[var(--bh-content-default)] shadow-[var(--shadow-sidebar)] transition-[width,background-color]",
105
+ "data-[collapsed=true]:w-[var(--bh-sidebar-width-collapsed)] data-[collapsed=true]:bg-[var(--bh-sidebar-bg-collapsed)]",
106
+ side === "end" && "ms-auto",
107
+ className
108
+ )}
109
+ {...props}
110
+ />
111
+ )
112
+ })
113
+
114
+ function SidebarHeader({ className, ...props }: SidebarSectionProps) {
115
+ return (
116
+ <div
117
+ data-slot="sidebar-header"
118
+ className={cn(
119
+ "flex min-h-[var(--bh-sidebar-item-height)] shrink-0 items-center gap-[var(--bh-sidebar-item-gap)] px-[var(--bh-sidebar-padding)] py-[var(--bh-space-xl-12)]",
120
+ className
121
+ )}
122
+ {...props}
123
+ />
124
+ )
125
+ }
126
+
127
+ function SidebarBody({ className, ...props }: SidebarSectionProps) {
128
+ return (
129
+ <div
130
+ data-slot="sidebar-body"
131
+ className={cn(
132
+ "min-h-0 flex-1 overflow-auto px-[var(--bh-sidebar-padding)] py-[var(--bh-space-xl-12)]",
133
+ className
134
+ )}
135
+ {...props}
136
+ />
137
+ )
138
+ }
139
+
140
+ function SidebarFooter({ className, ...props }: SidebarSectionProps) {
141
+ return (
142
+ <div
143
+ data-slot="sidebar-footer"
144
+ className={cn(
145
+ "shrink-0 border-t border-[var(--bh-sidebar-border)] px-[var(--bh-sidebar-padding)] py-[var(--bh-space-xl-12)]",
146
+ className
147
+ )}
148
+ {...props}
149
+ />
150
+ )
151
+ }
152
+
153
+ function SidebarGroup({ className, ...props }: SidebarSectionProps) {
154
+ return (
155
+ <div
156
+ data-slot="sidebar-group"
157
+ className={cn("grid gap-[var(--bh-space-md-8)]", className)}
158
+ {...props}
159
+ />
160
+ )
161
+ }
162
+
163
+ function SidebarGroupLabel({ className, ...props }: SidebarGroupLabelProps) {
164
+ const { collapsed } = useSidebarContext()
165
+
166
+ if (collapsed) return null
167
+
168
+ return (
169
+ <div
170
+ data-slot="sidebar-group-label"
171
+ dir="auto"
172
+ className={cn(
173
+ "px-[var(--bh-sidebar-item-padding-x)] text-[length:var(--bh-text-body-xs-medium-font-size)] font-[var(--bh-text-body-xs-medium-font-weight)] uppercase leading-[var(--bh-text-body-xs-medium-line-height)] tracking-[var(--bh-text-body-xs-medium-letter-spacing)] text-[var(--bh-content-muted)]",
174
+ className
175
+ )}
176
+ {...props}
177
+ />
178
+ )
179
+ }
180
+
181
+ function SidebarMenu({ className, ...props }: SidebarMenuProps) {
182
+ return (
183
+ <ul
184
+ data-slot="sidebar-menu"
185
+ className={cn("m-0 grid list-none gap-[var(--bh-space-xs-4)] p-0", className)}
186
+ {...props}
187
+ />
188
+ )
189
+ }
190
+
191
+ function SidebarMenuItem({ className, ...props }: SidebarMenuItemProps) {
192
+ return (
193
+ <li
194
+ data-slot="sidebar-menu-item"
195
+ className={cn("min-w-0", className)}
196
+ {...props}
197
+ />
198
+ )
199
+ }
200
+
201
+ const SidebarMenuButton = React.forwardRef<
202
+ HTMLButtonElement,
203
+ SidebarMenuButtonProps
204
+ >(function SidebarMenuButton(
205
+ { active = false, asChild = false, children, className, icon, ...props },
206
+ ref
207
+ ) {
208
+ const { collapsed } = useSidebarContext()
209
+ const Comp = asChild ? Slot : "button"
210
+
211
+ return (
212
+ <Comp
213
+ aria-current={active ? "page" : undefined}
214
+ data-active={active ? "true" : undefined}
215
+ data-slot="sidebar-menu-button"
216
+ ref={ref}
217
+ className={cn(
218
+ "flex h-[var(--bh-sidebar-item-height)] w-full min-w-0 items-center gap-[var(--bh-sidebar-item-gap)] rounded-[var(--bh-radius-lg-8)] px-[var(--bh-sidebar-item-padding-x)] text-start text-[length:var(--bh-text-body-sm-medium-font-size)] font-[var(--bh-text-body-sm-medium-font-weight)] leading-[var(--bh-text-body-sm-medium-line-height)] tracking-[var(--bh-text-body-sm-medium-letter-spacing)] text-[var(--bh-sidebar-item-content)] outline-none transition-[background-color,box-shadow,color]",
219
+ "hover:bg-[var(--bh-sidebar-item-bg-hover)] focus-visible:shadow-[var(--shadow-button-focus)] data-[active=true]:bg-[var(--bh-sidebar-item-bg-active)] data-[active=true]:text-[var(--bh-sidebar-item-content-active)]",
220
+ collapsed && "justify-center px-[var(--bh-space-md-8)]",
221
+ className
222
+ )}
223
+ {...props}
224
+ >
225
+ {icon ? (
226
+ <span
227
+ aria-hidden="true"
228
+ data-slot="sidebar-menu-icon"
229
+ className="inline-flex size-[var(--bh-sidebar-icon-size)] shrink-0 items-center justify-center"
230
+ >
231
+ {icon}
232
+ </span>
233
+ ) : null}
234
+ {collapsed ? null : (
235
+ <span data-slot="sidebar-menu-label" dir="auto" className="min-w-0 flex-1 truncate">
236
+ {children}
237
+ </span>
238
+ )}
239
+ </Comp>
240
+ )
241
+ })
242
+
243
+ const SidebarToggle = React.forwardRef<HTMLButtonElement, SidebarToggleProps>(
244
+ function SidebarToggle({ children, className, onClick, type = "button", ...props }, ref) {
245
+ const { collapsed, toggle } = useSidebarContext()
246
+
247
+ return (
248
+ <button
249
+ aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
250
+ aria-pressed={collapsed}
251
+ data-slot="sidebar-toggle"
252
+ ref={ref}
253
+ type={type}
254
+ className={cn(
255
+ "inline-flex size-[var(--bh-sidebar-item-height)] items-center justify-center rounded-[var(--bh-radius-lg-8)] text-[var(--bh-content-subtle)] outline-none transition-[background-color,box-shadow,color] hover:bg-[var(--bh-interactive-ghost-hover)] focus-visible:shadow-[var(--shadow-button-focus)]",
256
+ className
257
+ )}
258
+ onClick={(event) => {
259
+ onClick?.(event)
260
+ if (!event.defaultPrevented) toggle()
261
+ }}
262
+ {...props}
263
+ >
264
+ {children ?? (
265
+ <PanelLeftIcon
266
+ aria-hidden="true"
267
+ className="size-[var(--bh-space-5xl-24)] rtl:-scale-x-100"
268
+ strokeWidth={2}
269
+ />
270
+ )}
271
+ </button>
272
+ )
273
+ }
274
+ )
275
+
276
+ const SidebarTrigger = SidebarToggle
277
+
278
+ const SidebarRail = React.forwardRef<HTMLButtonElement, SidebarRailProps>(
279
+ function SidebarRail({ className, onClick, type = "button", ...props }, ref) {
280
+ const { toggle } = useSidebarContext()
281
+
282
+ return (
283
+ <button
284
+ aria-label="Toggle sidebar"
285
+ data-slot="sidebar-rail"
286
+ ref={ref}
287
+ type={type}
288
+ className={cn(
289
+ "absolute inset-y-0 end-[calc(var(--bh-sidebar-rail-width)*-1)] hidden w-[var(--bh-sidebar-rail-width)] cursor-ew-resize bg-transparent outline-none lg:block",
290
+ className
291
+ )}
292
+ onClick={(event) => {
293
+ onClick?.(event)
294
+ if (!event.defaultPrevented) toggle()
295
+ }}
296
+ {...props}
297
+ />
298
+ )
299
+ }
300
+ )
301
+
302
+ const SidebarInset = React.forwardRef<HTMLElement, SidebarInsetProps>(
303
+ function SidebarInset({ className, ...props }, ref) {
304
+ return (
305
+ <main
306
+ data-slot="sidebar-inset"
307
+ ref={ref}
308
+ className={cn("min-w-0 flex-1", className)}
309
+ {...props}
310
+ />
311
+ )
312
+ }
313
+ )
314
+
315
+ function useSidebarContext() {
316
+ const context = React.useContext(SidebarContext)
317
+ if (!context) {
318
+ throw new Error("Sidebar components must be used within SidebarProvider")
319
+ }
320
+
321
+ return context
322
+ }
323
+
324
+ export {
325
+ Sidebar,
326
+ SidebarBody,
327
+ SidebarFooter,
328
+ SidebarGroup,
329
+ SidebarGroupLabel,
330
+ SidebarHeader,
331
+ SidebarInset,
332
+ SidebarMenu,
333
+ SidebarMenuButton,
334
+ SidebarMenuItem,
335
+ SidebarProvider,
336
+ SidebarRail,
337
+ SidebarTrigger,
338
+ SidebarToggle,
339
+ }
340
+ export type {
341
+ SidebarGroupLabelProps,
342
+ SidebarInsetProps,
343
+ SidebarMenuButtonProps,
344
+ SidebarMenuItemProps,
345
+ SidebarMenuProps,
346
+ SidebarProps,
347
+ SidebarProviderProps,
348
+ SidebarRailProps,
349
+ SidebarTriggerProps,
350
+ SidebarSectionProps,
351
+ SidebarToggleProps,
352
+ }