banhaten 0.1.1 → 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 (258) hide show
  1. package/README.md +86 -309
  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 -59
  85. package/registry/components/alert-dialog.tsx +297 -0
  86. package/registry/components/aspect-ratio.tsx +30 -0
  87. package/registry/components/autocomplete.tsx +637 -0
  88. package/registry/components/avatar.tsx +258 -22
  89. package/registry/components/badge.tsx +97 -35
  90. package/registry/components/carousel.tsx +234 -0
  91. package/registry/components/chart.tsx +170 -0
  92. package/registry/components/collapsible.tsx +69 -0
  93. package/registry/components/command.tsx +174 -0
  94. package/registry/components/context-menu.tsx +236 -0
  95. package/registry/components/date-picker-state.ts +253 -0
  96. package/registry/components/date-picker.tsx +116 -159
  97. package/registry/components/expanded/EmptyState.tsx +155 -0
  98. package/registry/components/expanded/PageHeader.tsx +1 -1
  99. package/registry/components/expanded/breadcrumbs.css +139 -139
  100. package/registry/components/expanded/catalogComponentsShowcase.css +83 -83
  101. package/registry/components/expanded/emptyState.css +111 -0
  102. package/registry/components/expanded/slideout.css +1 -0
  103. package/registry/components/expanded/steps.css +274 -274
  104. package/registry/components/expanded/table.css +1 -0
  105. package/registry/components/expanded/timeline.css +264 -264
  106. package/registry/components/field.tsx +230 -0
  107. package/registry/components/hover-card.tsx +48 -0
  108. package/registry/components/input-group.tsx +130 -0
  109. package/registry/components/input-otp.tsx +574 -0
  110. package/registry/components/input.tsx +22 -12
  111. package/registry/components/kbd.tsx +44 -0
  112. package/registry/components/label.tsx +78 -0
  113. package/registry/components/menu.tsx +373 -8
  114. package/registry/components/menubar.tsx +226 -0
  115. package/registry/components/modal.tsx +109 -76
  116. package/registry/components/native-select.tsx +205 -0
  117. package/registry/components/navigation-menu.tsx +171 -0
  118. package/registry/components/popover.tsx +840 -0
  119. package/registry/components/radio-group.tsx +1 -1
  120. package/registry/components/resizable.tsx +74 -0
  121. package/registry/components/scroll-area.tsx +67 -0
  122. package/registry/components/select.tsx +6 -4
  123. package/registry/components/sheet.tsx +305 -0
  124. package/registry/components/sidebar.tsx +352 -0
  125. package/registry/components/skeleton.css +57 -0
  126. package/registry/components/skeleton.tsx +482 -0
  127. package/registry/components/social-button.tsx +74 -10
  128. package/registry/components/spinner.tsx +79 -11
  129. package/registry/components/{expanded/tabs.css → tabs.css} +127 -106
  130. package/registry/components/tabs.tsx +242 -0
  131. package/registry/components/textarea.tsx +2 -2
  132. package/registry/components/toast.tsx +131 -0
  133. package/registry/components/tooltip.tsx +4 -0
  134. package/registry/examples/alert-dialog-demo.tsx +42 -0
  135. package/registry/examples/aspect-ratio-demo.tsx +11 -0
  136. package/registry/examples/autocomplete-demo.tsx +109 -0
  137. package/registry/examples/avatar-demo.tsx +102 -47
  138. package/registry/examples/badge-demo.tsx +16 -0
  139. package/registry/examples/carousel-demo.tsx +25 -0
  140. package/registry/examples/chart-demo.tsx +33 -0
  141. package/registry/examples/collapsible-demo.tsx +16 -0
  142. package/registry/examples/command-demo.tsx +42 -0
  143. package/registry/examples/context-menu-demo.tsx +29 -0
  144. package/registry/examples/expanded/command-bar-demo.tsx +236 -0
  145. package/registry/examples/expanded/empty-state-demo.tsx +39 -0
  146. package/registry/examples/expanded/tabs-demo.tsx +1 -1
  147. package/registry/examples/field-demo.tsx +51 -0
  148. package/registry/examples/hover-card-demo.tsx +23 -0
  149. package/registry/examples/input-demo.tsx +1 -1
  150. package/registry/examples/input-group-demo.tsx +16 -0
  151. package/registry/examples/input-otp-demo.tsx +72 -0
  152. package/registry/examples/kbd-demo.tsx +11 -0
  153. package/registry/examples/label-demo.tsx +20 -0
  154. package/registry/examples/menu-demo.tsx +101 -88
  155. package/registry/examples/menubar-demo.tsx +34 -0
  156. package/registry/examples/native-select-demo.tsx +16 -0
  157. package/registry/examples/navigation-menu-demo.tsx +29 -0
  158. package/registry/examples/popover-demo.tsx +546 -0
  159. package/registry/examples/resizable-demo.tsx +22 -0
  160. package/registry/examples/scroll-area-demo.tsx +15 -0
  161. package/registry/examples/select-demo.tsx +1 -1
  162. package/registry/examples/sheet-demo.tsx +47 -0
  163. package/registry/examples/sidebar-demo.tsx +55 -0
  164. package/registry/examples/skeleton-demo.tsx +56 -0
  165. package/registry/examples/spinner-demo.tsx +23 -1
  166. package/registry/examples/tabs-demo.tsx +13 -0
  167. package/registry/examples/textarea-demo.tsx +1 -1
  168. package/registry/examples/toast-demo.tsx +35 -0
  169. package/registry/index.json +895 -19
  170. package/registry/styles/globals.css +4733 -4602
  171. package/registry.json +1612 -0
  172. package/schema/config.schema.json +48 -0
  173. package/schema/registry.schema.json +85 -0
  174. package/schema/tokens.schema.json +63 -0
  175. package/src/cli/index.js +1413 -184
  176. package/tokens/banhaten.tokens.json +1 -1
  177. package/registry/assets/avatars/avatar-02.jpg +0 -0
  178. package/registry/assets/avatars/avatar-03.jpg +0 -0
  179. package/registry/assets/avatars/avatar-04.jpg +0 -0
  180. package/registry/assets/avatars/avatar-05.jpg +0 -0
  181. package/registry/assets/avatars/avatar-06.jpg +0 -0
  182. package/registry/assets/avatars/avatar-07.jpg +0 -0
  183. package/registry/assets/avatars/avatar-08.jpg +0 -0
  184. package/registry/assets/avatars/avatar-09.jpg +0 -0
  185. package/registry/assets/avatars/avatar-10.jpg +0 -0
  186. package/registry/assets/avatars/avatar-11.jpg +0 -0
  187. package/registry/assets/avatars/avatar-12.jpg +0 -0
  188. package/registry/assets/avatars/avatar-13.jpg +0 -0
  189. package/registry/assets/avatars/avatar-14.jpg +0 -0
  190. package/registry/assets/avatars/avatar-15.jpg +0 -0
  191. package/registry/assets/avatars/avatar-16.jpg +0 -0
  192. package/registry/assets/avatars/avatar-17.jpg +0 -0
  193. package/registry/assets/avatars/avatar-18.jpg +0 -0
  194. package/registry/assets/avatars/avatar-19.jpg +0 -0
  195. package/registry/assets/avatars/avatar-20.jpg +0 -0
  196. package/registry/assets/avatars/avatar-21.jpg +0 -0
  197. package/registry/assets/avatars/avatar-22.jpg +0 -0
  198. package/registry/assets/avatars/avatar-23.jpg +0 -0
  199. package/registry/assets/avatars/avatar-24.jpg +0 -0
  200. package/registry/assets/avatars/avatar-25.jpg +0 -0
  201. package/registry/assets/avatars/avatar-26.jpg +0 -0
  202. package/registry/assets/avatars/avatar-27.jpg +0 -0
  203. package/registry/assets/avatars/avatar-28.jpg +0 -0
  204. package/registry/assets/avatars/avatar-29.jpg +0 -0
  205. package/registry/assets/avatars/avatar-30.jpg +0 -0
  206. package/registry/assets/avatars/avatar-31.jpg +0 -0
  207. package/registry/assets/avatars/avatar-32.jpg +0 -0
  208. package/registry/assets/avatars/avatar-33.jpg +0 -0
  209. package/registry/assets/avatars/avatar-34.jpg +0 -0
  210. package/registry/assets/avatars/avatar-35.jpg +0 -0
  211. package/registry/assets/image-assets.json +0 -744
  212. package/registry/assets/images/art-02.jpg +0 -0
  213. package/registry/assets/images/art-03.jpg +0 -0
  214. package/registry/assets/images/art-04.jpg +0 -0
  215. package/registry/assets/images/art-05.jpg +0 -0
  216. package/registry/assets/images/art-06.jpg +0 -0
  217. package/registry/assets/images/art-07.jpg +0 -0
  218. package/registry/assets/images/art-08.jpg +0 -0
  219. package/registry/assets/images/art-09.jpg +0 -0
  220. package/registry/assets/images/art-10.jpg +0 -0
  221. package/registry/assets/images/art-11.jpg +0 -0
  222. package/registry/assets/images/art-12.jpg +0 -0
  223. package/registry/assets/images/art-13.jpg +0 -0
  224. package/registry/assets/images/art-14.jpg +0 -0
  225. package/registry/assets/images/art-15.jpg +0 -0
  226. package/registry/assets/images/art-16.jpg +0 -0
  227. package/registry/assets/images/art-17.jpg +0 -0
  228. package/registry/assets/images/art-18.jpg +0 -0
  229. package/registry/assets/images/art-19.jpg +0 -0
  230. package/registry/assets/images/art-20.jpg +0 -0
  231. package/registry/assets/images/art-21.jpg +0 -0
  232. package/registry/assets/images/art-22.jpg +0 -0
  233. package/registry/assets/images/art-23.jpg +0 -0
  234. package/registry/assets/images/art-24.jpg +0 -0
  235. package/registry/assets/images/art-25.jpg +0 -0
  236. package/registry/assets/images/art-26.jpg +0 -0
  237. package/registry/assets/images/art-27.jpg +0 -0
  238. package/registry/assets/images/nature-01.jpg +0 -0
  239. package/registry/assets/images/nature-02.jpg +0 -0
  240. package/registry/assets/images/nature-03.jpg +0 -0
  241. package/registry/assets/images/nature-04.jpg +0 -0
  242. package/registry/assets/images/nature-05.jpg +0 -0
  243. package/registry/assets/images/nature-06.jpg +0 -0
  244. package/registry/assets/images/nature-07.jpg +0 -0
  245. package/registry/assets/images/nature-08.jpg +0 -0
  246. package/registry/assets/images/nature-09.jpg +0 -0
  247. package/registry/assets/images/nature-10.jpg +0 -0
  248. package/registry/assets/images/nature-11.jpg +0 -0
  249. package/registry/assets/images/nature-12.jpg +0 -0
  250. package/registry/assets/images/nature-13.jpg +0 -0
  251. package/registry/assets/images/nature-14.jpg +0 -0
  252. package/registry/assets/images/nature-15.jpg +0 -0
  253. package/registry/assets/images/nature-16.jpg +0 -0
  254. package/registry/assets/images/nature-17.jpg +0 -0
  255. package/registry/assets/images/nature-18.jpg +0 -0
  256. package/registry/assets/images/nature-19.jpg +0 -0
  257. package/registry/assets/images/nature-20.jpg +0 -0
  258. package/registry/components/expanded/Tabs.tsx +0 -86
@@ -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
+ }
@@ -0,0 +1,57 @@
1
+ [data-slot="skeleton"] {
2
+ --bh-skeleton-bg: var(--bh-bg-muted);
3
+ --bh-skeleton-highlight: var(--bh-bg-raised-subtle);
4
+ --bh-skeleton-duration: 1.4s;
5
+ --bh-skeleton-radius: var(--bh-radius-md-6);
6
+ --bh-skeleton-shimmer-width: 62%;
7
+ --bh-skeleton-width: 100%;
8
+ --bh-skeleton-height: var(--bh-space-4xl-20);
9
+ }
10
+
11
+ [data-slot="skeleton"][data-animated="true"]::after {
12
+ animation: bh-skeleton-shimmer var(--bh-skeleton-duration) ease-in-out infinite;
13
+ background: linear-gradient(
14
+ 90deg,
15
+ var(--bh-alpha-alpha-transparent),
16
+ var(--bh-skeleton-highlight),
17
+ var(--bh-alpha-alpha-transparent)
18
+ );
19
+ content: "";
20
+ inset-block: 0;
21
+ inset-inline-start: 0;
22
+ pointer-events: none;
23
+ position: absolute;
24
+ transform: translateX(-100%);
25
+ width: var(--bh-skeleton-shimmer-width);
26
+ }
27
+
28
+ [dir="rtl"] [data-slot="skeleton"][data-animated="true"]::after,
29
+ [data-slot="skeleton"][dir="rtl"][data-animated="true"]::after {
30
+ animation-name: bh-skeleton-shimmer-rtl;
31
+ }
32
+
33
+ @keyframes bh-skeleton-shimmer {
34
+ from {
35
+ transform: translateX(-100%);
36
+ }
37
+
38
+ to {
39
+ transform: translateX(200%);
40
+ }
41
+ }
42
+
43
+ @keyframes bh-skeleton-shimmer-rtl {
44
+ from {
45
+ transform: translateX(100%);
46
+ }
47
+
48
+ to {
49
+ transform: translateX(-200%);
50
+ }
51
+ }
52
+
53
+ @media (prefers-reduced-motion: reduce) {
54
+ [data-slot="skeleton"][data-animated="true"]::after {
55
+ animation: none;
56
+ }
57
+ }