@blips/ui 1.0.1 → 2.0.0

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 (59) hide show
  1. package/dist/index.cjs +3612 -2515
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +329 -484
  4. package/dist/index.d.ts +329 -484
  5. package/dist/index.js +3602 -2513
  6. package/dist/index.js.map +1 -1
  7. package/package.json +14 -12
  8. package/src/components/accordion.tsx +56 -46
  9. package/src/components/alert-dialog.tsx +166 -109
  10. package/src/components/alert.tsx +45 -38
  11. package/src/components/aspect-ratio.tsx +7 -1
  12. package/src/components/avatar.tsx +104 -45
  13. package/src/components/badge.tsx +25 -13
  14. package/src/components/breadcrumb.tsx +76 -82
  15. package/src/components/button-group.tsx +2 -2
  16. package/src/components/button.tsx +36 -28
  17. package/src/components/calendar.tsx +35 -28
  18. package/src/components/card.tsx +83 -70
  19. package/src/components/carousel.tsx +118 -137
  20. package/src/components/chart.tsx +197 -208
  21. package/src/components/checkbox.tsx +25 -21
  22. package/src/components/collapsible.tsx +25 -3
  23. package/src/components/command.tsx +138 -105
  24. package/src/components/context-menu.tsx +215 -161
  25. package/src/components/dialog.tsx +127 -91
  26. package/src/components/drawer.tsx +102 -83
  27. package/src/components/dropdown-menu.tsx +227 -170
  28. package/src/components/form.tsx +41 -52
  29. package/src/components/hover-card.tsx +36 -19
  30. package/src/components/input-group.tsx +4 -4
  31. package/src/components/input-otp.tsx +51 -43
  32. package/src/components/input.tsx +16 -17
  33. package/src/components/kbd.tsx +1 -1
  34. package/src/components/label.tsx +16 -18
  35. package/src/components/menubar.tsx +214 -192
  36. package/src/components/navigation-menu.tsx +140 -98
  37. package/src/components/pagination.tsx +97 -87
  38. package/src/components/popover.tsx +83 -23
  39. package/src/components/progress.tsx +23 -20
  40. package/src/components/radio-group.tsx +23 -20
  41. package/src/components/resizable.tsx +39 -31
  42. package/src/components/scroll-area.tsx +51 -39
  43. package/src/components/select.tsx +161 -131
  44. package/src/components/separator.tsx +13 -14
  45. package/src/components/sheet.tsx +112 -109
  46. package/src/components/sidebar.tsx +422 -470
  47. package/src/components/skeleton.tsx +4 -6
  48. package/src/components/slider.tsx +57 -20
  49. package/src/components/sonner.tsx +19 -24
  50. package/src/components/spinner.tsx +3 -3
  51. package/src/components/switch.tsx +28 -20
  52. package/src/components/table.tsx +94 -95
  53. package/src/components/tabs.tsx +88 -50
  54. package/src/components/textarea.tsx +5 -9
  55. package/src/components/toggle-group.tsx +52 -30
  56. package/src/components/toggle.tsx +24 -20
  57. package/src/components/tooltip.tsx +46 -19
  58. package/src/globals.css +213 -96
  59. package/src/index.ts +27 -6
@@ -1,29 +1,29 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import { Slot } from "@radix-ui/react-slot"
5
4
  import { cva, type VariantProps } from "class-variance-authority"
6
- import { PanelLeft } from "lucide-react"
5
+ import { SidebarSimple } from "@phosphor-icons/react"
6
+ import { Slot } from "@radix-ui/react-slot"
7
7
 
8
- import { useIsMobile } from "@/hooks/use-mobile"
9
- import { cn } from "@/lib/utils"
10
- import { Button } from "@/components/button"
11
- import { Input } from "@/components/input"
12
- import { Separator } from "@/components/separator"
8
+ import { useIsMobile } from "../hooks/use-mobile"
9
+ import { cn } from "../lib/utils"
10
+ import { Button } from "./button"
11
+ import { Input } from "./input"
12
+ import { Separator } from "./separator"
13
13
  import {
14
14
  Sheet,
15
15
  SheetContent,
16
16
  SheetDescription,
17
17
  SheetHeader,
18
18
  SheetTitle,
19
- } from "@/components/sheet"
20
- import { Skeleton } from "@/components/skeleton"
19
+ } from "./sheet"
20
+ import { Skeleton } from "./skeleton"
21
21
  import {
22
22
  Tooltip,
23
23
  TooltipContent,
24
24
  TooltipProvider,
25
25
  TooltipTrigger,
26
- } from "@/components/tooltip"
26
+ } from "./tooltip"
27
27
 
28
28
  const SIDEBAR_COOKIE_NAME = "sidebar_state"
29
29
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
@@ -53,268 +53,248 @@ function useSidebar() {
53
53
  return context
54
54
  }
55
55
 
56
- const SidebarProvider = React.forwardRef<
57
- HTMLDivElement,
58
- React.ComponentProps<"div"> & {
59
- defaultOpen?: boolean
60
- open?: boolean
61
- onOpenChange?: (open: boolean) => void
62
- }
63
- >(
64
- (
65
- {
66
- defaultOpen = true,
67
- open: openProp,
68
- onOpenChange: setOpenProp,
69
- className,
70
- style,
71
- children,
72
- ...props
73
- },
74
- ref
75
- ) => {
76
- const isMobile = useIsMobile()
77
- const [openMobile, setOpenMobile] = React.useState(false)
78
-
79
- // This is the internal state of the sidebar.
80
- // We use openProp and setOpenProp for control from outside the component.
81
- const [_open, _setOpen] = React.useState(defaultOpen)
82
- const open = openProp ?? _open
83
- const setOpen = React.useCallback(
84
- (value: boolean | ((value: boolean) => boolean)) => {
85
- const openState = typeof value === "function" ? value(open) : value
86
- if (setOpenProp) {
87
- setOpenProp(openState)
88
- } else {
89
- _setOpen(openState)
90
- }
56
+ function SidebarProvider({
57
+ defaultOpen = true,
58
+ open: openProp,
59
+ onOpenChange: setOpenProp,
60
+ className,
61
+ style,
62
+ children,
63
+ ...props
64
+ }: React.ComponentProps<"div"> & {
65
+ defaultOpen?: boolean
66
+ open?: boolean
67
+ onOpenChange?: (open: boolean) => void
68
+ }) {
69
+ const isMobile = useIsMobile()
70
+ const [openMobile, setOpenMobile] = React.useState(false)
71
+
72
+ // This is the internal state of the sidebar.
73
+ // We use openProp and setOpenProp for control from outside the component.
74
+ const [_open, _setOpen] = React.useState(defaultOpen)
75
+ const open = openProp ?? _open
76
+ const setOpen = React.useCallback(
77
+ (value: boolean | ((value: boolean) => boolean)) => {
78
+ const openState = typeof value === "function" ? value(open) : value
79
+ if (setOpenProp) {
80
+ setOpenProp(openState)
81
+ } else {
82
+ _setOpen(openState)
83
+ }
91
84
 
92
- // This sets the cookie to keep the sidebar state.
93
- // biome-ignore lint/suspicious/noDocumentCookie: shadcn/ui pattern for sidebar state persistence
94
- document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
95
- },
96
- [setOpenProp, open]
97
- )
85
+ // This sets the cookie to keep the sidebar state.
86
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
87
+ },
88
+ [setOpenProp, open]
89
+ )
98
90
 
99
- // Helper to toggle the sidebar.
100
- const toggleSidebar = React.useCallback(() => {
101
- return isMobile
102
- ? setOpenMobile((open) => !open)
103
- : setOpen((open) => !open)
104
- }, [isMobile, setOpen])
105
-
106
- // Adds a keyboard shortcut to toggle the sidebar.
107
- React.useEffect(() => {
108
- const handleKeyDown = (event: KeyboardEvent) => {
109
- if (
110
- event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
111
- (event.metaKey || event.ctrlKey)
112
- ) {
113
- event.preventDefault()
114
- toggleSidebar()
115
- }
91
+ // Helper to toggle the sidebar.
92
+ const toggleSidebar = React.useCallback(() => {
93
+ return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)
94
+ }, [isMobile, setOpen, setOpenMobile])
95
+
96
+ // Adds a keyboard shortcut to toggle the sidebar.
97
+ React.useEffect(() => {
98
+ const handleKeyDown = (event: KeyboardEvent) => {
99
+ if (
100
+ event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
101
+ (event.metaKey || event.ctrlKey)
102
+ ) {
103
+ event.preventDefault()
104
+ toggleSidebar()
116
105
  }
106
+ }
117
107
 
118
- window.addEventListener("keydown", handleKeyDown)
119
- return () => window.removeEventListener("keydown", handleKeyDown)
120
- }, [toggleSidebar])
121
-
122
- // We add a state so that we can do data-state="expanded" or "collapsed".
123
- // This makes it easier to style the sidebar with Tailwind classes.
124
- const state = open ? "expanded" : "collapsed"
125
-
126
- const contextValue = React.useMemo<SidebarContextProps>(
127
- () => ({
128
- state,
129
- open,
130
- setOpen,
131
- isMobile,
132
- openMobile,
133
- setOpenMobile,
134
- toggleSidebar,
135
- }),
136
- [state, open, setOpen, isMobile, openMobile, toggleSidebar]
137
- )
138
-
139
- return (
140
- <SidebarContext.Provider value={contextValue}>
141
- <TooltipProvider delayDuration={0}>
142
- <div
143
- style={
144
- {
145
- "--sidebar-width": SIDEBAR_WIDTH,
146
- "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
147
- ...style,
148
- } as React.CSSProperties
149
- }
150
- className={cn(
151
- "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar",
152
- className
153
- )}
154
- ref={ref}
155
- {...props}
156
- >
157
- {children}
158
- </div>
159
- </TooltipProvider>
160
- </SidebarContext.Provider>
161
- )
162
- }
163
- )
164
- SidebarProvider.displayName = "SidebarProvider"
165
-
166
- const Sidebar = React.forwardRef<
167
- HTMLDivElement,
168
- React.ComponentProps<"div"> & {
169
- side?: "left" | "right"
170
- variant?: "sidebar" | "floating" | "inset"
171
- collapsible?: "offcanvas" | "icon" | "none"
172
- }
173
- >(
174
- (
175
- {
176
- side = "left",
177
- variant = "sidebar",
178
- collapsible = "offcanvas",
179
- className,
180
- children,
181
- ...props
182
- },
183
- ref
184
- ) => {
185
- const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
108
+ window.addEventListener("keydown", handleKeyDown)
109
+ return () => window.removeEventListener("keydown", handleKeyDown)
110
+ }, [toggleSidebar])
111
+
112
+ // We add a state so that we can do data-state="expanded" or "collapsed".
113
+ // This makes it easier to style the sidebar with Tailwind classes.
114
+ const state = open ? "expanded" : "collapsed"
115
+
116
+ const contextValue = React.useMemo<SidebarContextProps>(
117
+ () => ({
118
+ state,
119
+ open,
120
+ setOpen,
121
+ isMobile,
122
+ openMobile,
123
+ setOpenMobile,
124
+ toggleSidebar,
125
+ }),
126
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
127
+ )
186
128
 
187
- if (collapsible === "none") {
188
- return (
129
+ return (
130
+ <SidebarContext.Provider value={contextValue}>
131
+ <TooltipProvider delayDuration={0}>
189
132
  <div
133
+ data-slot="sidebar-wrapper"
134
+ style={
135
+ {
136
+ "--sidebar-width": SIDEBAR_WIDTH,
137
+ "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
138
+ ...style,
139
+ } as React.CSSProperties
140
+ }
190
141
  className={cn(
191
- "flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground",
142
+ "group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
192
143
  className
193
144
  )}
194
- ref={ref}
195
145
  {...props}
196
146
  >
197
147
  {children}
198
148
  </div>
199
- )
200
- }
149
+ </TooltipProvider>
150
+ </SidebarContext.Provider>
151
+ )
152
+ }
201
153
 
202
- if (isMobile) {
203
- return (
204
- <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
205
- <SheetContent
206
- data-sidebar="sidebar"
207
- data-mobile="true"
208
- className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
209
- style={
210
- {
211
- "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
212
- } as React.CSSProperties
213
- }
214
- side={side}
215
- >
216
- <SheetHeader className="sr-only">
217
- <SheetTitle>Sidebar</SheetTitle>
218
- <SheetDescription>Displays the mobile sidebar.</SheetDescription>
219
- </SheetHeader>
220
- <div className="flex h-full w-full flex-col">{children}</div>
221
- </SheetContent>
222
- </Sheet>
223
- )
224
- }
154
+ function Sidebar({
155
+ side = "left",
156
+ variant = "sidebar",
157
+ collapsible = "offcanvas",
158
+ className,
159
+ children,
160
+ ...props
161
+ }: React.ComponentProps<"div"> & {
162
+ side?: "left" | "right"
163
+ variant?: "sidebar" | "floating" | "inset"
164
+ collapsible?: "offcanvas" | "icon" | "none"
165
+ }) {
166
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
167
+
168
+ if (collapsible === "none") {
169
+ return (
170
+ <div
171
+ data-slot="sidebar"
172
+ className={cn(
173
+ "flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
174
+ className
175
+ )}
176
+ {...props}
177
+ >
178
+ {children}
179
+ </div>
180
+ )
181
+ }
225
182
 
183
+ if (isMobile) {
226
184
  return (
185
+ <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
186
+ <SheetContent
187
+ data-sidebar="sidebar"
188
+ data-slot="sidebar"
189
+ data-mobile="true"
190
+ className="w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
191
+ style={
192
+ {
193
+ "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
194
+ } as React.CSSProperties
195
+ }
196
+ side={side}
197
+ >
198
+ <SheetHeader className="sr-only">
199
+ <SheetTitle>Sidebar</SheetTitle>
200
+ <SheetDescription>Displays the mobile sidebar.</SheetDescription>
201
+ </SheetHeader>
202
+ <div className="flex h-full w-full flex-col">{children}</div>
203
+ </SheetContent>
204
+ </Sheet>
205
+ )
206
+ }
207
+
208
+ return (
209
+ <div
210
+ className="group peer hidden text-sidebar-foreground md:block"
211
+ data-state={state}
212
+ data-collapsible={state === "collapsed" ? collapsible : ""}
213
+ data-variant={variant}
214
+ data-side={side}
215
+ data-slot="sidebar"
216
+ >
217
+ {/* This is what handles the sidebar gap on desktop */}
227
218
  <div
228
- ref={ref}
229
- className="group peer hidden text-sidebar-foreground md:block"
230
- data-state={state}
231
- data-collapsible={state === "collapsed" ? collapsible : ""}
232
- data-variant={variant}
233
- data-side={side}
219
+ data-slot="sidebar-gap"
220
+ className={cn(
221
+ "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
222
+ "group-data-[collapsible=offcanvas]:w-0",
223
+ "group-data-[side=right]:rotate-180",
224
+ variant === "floating" || variant === "inset"
225
+ ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
226
+ : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
227
+ )}
228
+ />
229
+ <div
230
+ data-slot="sidebar-container"
231
+ className={cn(
232
+ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
233
+ side === "left"
234
+ ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
235
+ : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
236
+ // Adjust the padding for floating and inset variants.
237
+ variant === "floating" || variant === "inset"
238
+ ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
239
+ : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
240
+ className
241
+ )}
242
+ {...props}
234
243
  >
235
- {/* This is what handles the sidebar gap on desktop */}
236
244
  <div
237
- className={cn(
238
- "relative w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
239
- "group-data-[collapsible=offcanvas]:w-0",
240
- "group-data-[side=right]:rotate-180",
241
- variant === "floating" || variant === "inset"
242
- ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
243
- : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]"
244
- )}
245
- />
246
- <div
247
- className={cn(
248
- "fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex",
249
- side === "left"
250
- ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
251
- : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
252
- // Adjust the padding for floating and inset variants.
253
- variant === "floating" || variant === "inset"
254
- ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
255
- : "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
256
- className
257
- )}
258
- {...props}
245
+ data-sidebar="sidebar"
246
+ data-slot="sidebar-inner"
247
+ className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
259
248
  >
260
- <div
261
- data-sidebar="sidebar"
262
- className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
263
- >
264
- {children}
265
- </div>
249
+ {children}
266
250
  </div>
267
251
  </div>
268
- )
269
- }
270
- )
271
- Sidebar.displayName = "Sidebar"
252
+ </div>
253
+ )
254
+ }
272
255
 
273
- const SidebarTrigger = React.forwardRef<
274
- React.ElementRef<typeof Button>,
275
- React.ComponentProps<typeof Button>
276
- >(({ className, onClick, ...props }, ref) => {
256
+ function SidebarTrigger({
257
+ className,
258
+ onClick,
259
+ ...props
260
+ }: React.ComponentProps<typeof Button>) {
277
261
  const { toggleSidebar } = useSidebar()
278
262
 
279
263
  return (
280
264
  <Button
281
- ref={ref}
282
265
  data-sidebar="trigger"
266
+ data-slot="sidebar-trigger"
283
267
  variant="ghost"
284
268
  size="icon"
285
- className={cn("h-7 w-7", className)}
269
+ className={cn("size-7", className)}
286
270
  onClick={(event) => {
287
271
  onClick?.(event)
288
272
  toggleSidebar()
289
273
  }}
290
274
  {...props}
291
275
  >
292
- <PanelLeft />
276
+ <SidebarSimple />
293
277
  <span className="sr-only">Toggle Sidebar</span>
294
278
  </Button>
295
279
  )
296
- })
297
- SidebarTrigger.displayName = "SidebarTrigger"
280
+ }
298
281
 
299
- const SidebarRail = React.forwardRef<
300
- HTMLButtonElement,
301
- React.ComponentProps<"button">
302
- >(({ className, ...props }, ref) => {
282
+ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
303
283
  const { toggleSidebar } = useSidebar()
304
284
 
305
285
  return (
306
286
  <button
307
- ref={ref}
308
287
  data-sidebar="rail"
288
+ data-slot="sidebar-rail"
309
289
  aria-label="Toggle Sidebar"
310
290
  tabIndex={-1}
311
291
  onClick={toggleSidebar}
312
292
  title="Toggle Sidebar"
313
293
  className={cn(
314
- "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
315
- "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
294
+ "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex",
295
+ "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
316
296
  "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
317
- "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
297
+ "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
318
298
  "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
319
299
  "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
320
300
  className
@@ -322,97 +302,76 @@ const SidebarRail = React.forwardRef<
322
302
  {...props}
323
303
  />
324
304
  )
325
- })
326
- SidebarRail.displayName = "SidebarRail"
305
+ }
327
306
 
328
- const SidebarInset = React.forwardRef<
329
- HTMLDivElement,
330
- React.ComponentProps<"main">
331
- >(({ className, ...props }, ref) => {
307
+ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
332
308
  return (
333
309
  <main
334
- ref={ref}
310
+ data-slot="sidebar-inset"
335
311
  className={cn(
336
312
  "relative flex w-full flex-1 flex-col bg-background",
337
- "md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
313
+ "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
338
314
  className
339
315
  )}
340
316
  {...props}
341
317
  />
342
318
  )
343
- })
344
- SidebarInset.displayName = "SidebarInset"
319
+ }
345
320
 
346
- const SidebarInput = React.forwardRef<
347
- React.ElementRef<typeof Input>,
348
- React.ComponentProps<typeof Input>
349
- >(({ className, ...props }, ref) => {
321
+ function SidebarInput({
322
+ className,
323
+ ...props
324
+ }: React.ComponentProps<typeof Input>) {
350
325
  return (
351
326
  <Input
352
- ref={ref}
327
+ data-slot="sidebar-input"
353
328
  data-sidebar="input"
354
- className={cn(
355
- "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
356
- className
357
- )}
329
+ className={cn("h-8 w-full bg-background shadow-none", className)}
358
330
  {...props}
359
331
  />
360
332
  )
361
- })
362
- SidebarInput.displayName = "SidebarInput"
333
+ }
363
334
 
364
- const SidebarHeader = React.forwardRef<
365
- HTMLDivElement,
366
- React.ComponentProps<"div">
367
- >(({ className, ...props }, ref) => {
335
+ function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) {
368
336
  return (
369
337
  <div
370
- ref={ref}
338
+ data-slot="sidebar-header"
371
339
  data-sidebar="header"
372
340
  className={cn("flex flex-col gap-2 p-2", className)}
373
341
  {...props}
374
342
  />
375
343
  )
376
- })
377
- SidebarHeader.displayName = "SidebarHeader"
344
+ }
378
345
 
379
- const SidebarFooter = React.forwardRef<
380
- HTMLDivElement,
381
- React.ComponentProps<"div">
382
- >(({ className, ...props }, ref) => {
346
+ function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
383
347
  return (
384
348
  <div
385
- ref={ref}
349
+ data-slot="sidebar-footer"
386
350
  data-sidebar="footer"
387
351
  className={cn("flex flex-col gap-2 p-2", className)}
388
352
  {...props}
389
353
  />
390
354
  )
391
- })
392
- SidebarFooter.displayName = "SidebarFooter"
355
+ }
393
356
 
394
- const SidebarSeparator = React.forwardRef<
395
- React.ElementRef<typeof Separator>,
396
- React.ComponentProps<typeof Separator>
397
- >(({ className, ...props }, ref) => {
357
+ function SidebarSeparator({
358
+ className,
359
+ ...props
360
+ }: React.ComponentProps<typeof Separator>) {
398
361
  return (
399
362
  <Separator
400
- ref={ref}
363
+ data-slot="sidebar-separator"
401
364
  data-sidebar="separator"
402
365
  className={cn("mx-2 w-auto bg-sidebar-border", className)}
403
366
  {...props}
404
367
  />
405
368
  )
406
- })
407
- SidebarSeparator.displayName = "SidebarSeparator"
369
+ }
408
370
 
409
- const SidebarContent = React.forwardRef<
410
- HTMLDivElement,
411
- React.ComponentProps<"div">
412
- >(({ className, ...props }, ref) => {
371
+ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
413
372
  return (
414
373
  <div
415
- ref={ref}
374
+ data-slot="sidebar-content"
416
375
  data-sidebar="content"
417
376
  className={cn(
418
377
  "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
@@ -421,109 +380,101 @@ const SidebarContent = React.forwardRef<
421
380
  {...props}
422
381
  />
423
382
  )
424
- })
425
- SidebarContent.displayName = "SidebarContent"
383
+ }
426
384
 
427
- const SidebarGroup = React.forwardRef<
428
- HTMLDivElement,
429
- React.ComponentProps<"div">
430
- >(({ className, ...props }, ref) => {
385
+ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
431
386
  return (
432
387
  <div
433
- ref={ref}
388
+ data-slot="sidebar-group"
434
389
  data-sidebar="group"
435
390
  className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
436
391
  {...props}
437
392
  />
438
393
  )
439
- })
440
- SidebarGroup.displayName = "SidebarGroup"
394
+ }
441
395
 
442
- const SidebarGroupLabel = React.forwardRef<
443
- HTMLDivElement,
444
- React.ComponentProps<"div"> & { asChild?: boolean }
445
- >(({ className, asChild = false, ...props }, ref) => {
396
+ function SidebarGroupLabel({
397
+ className,
398
+ asChild = false,
399
+ ...props
400
+ }: React.ComponentProps<"div"> & { asChild?: boolean }) {
446
401
  const Comp = asChild ? Slot : "div"
447
402
 
448
403
  return (
449
404
  <Comp
450
- ref={ref}
405
+ data-slot="sidebar-group-label"
451
406
  data-sidebar="group-label"
452
407
  className={cn(
453
- "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
408
+ "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
454
409
  "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
455
410
  className
456
411
  )}
457
412
  {...props}
458
413
  />
459
414
  )
460
- })
461
- SidebarGroupLabel.displayName = "SidebarGroupLabel"
415
+ }
462
416
 
463
- const SidebarGroupAction = React.forwardRef<
464
- HTMLButtonElement,
465
- React.ComponentProps<"button"> & { asChild?: boolean }
466
- >(({ className, asChild = false, ...props }, ref) => {
417
+ function SidebarGroupAction({
418
+ className,
419
+ asChild = false,
420
+ ...props
421
+ }: React.ComponentProps<"button"> & { asChild?: boolean }) {
467
422
  const Comp = asChild ? Slot : "button"
468
423
 
469
424
  return (
470
425
  <Comp
471
- ref={ref}
426
+ data-slot="sidebar-group-action"
472
427
  data-sidebar="group-action"
473
428
  className={cn(
474
- "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
429
+ "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
475
430
  // Increases the hit area of the button on mobile.
476
- "after:absolute after:-inset-2 after:md:hidden",
431
+ "after:absolute after:-inset-2 md:after:hidden",
477
432
  "group-data-[collapsible=icon]:hidden",
478
433
  className
479
434
  )}
480
435
  {...props}
481
436
  />
482
437
  )
483
- })
484
- SidebarGroupAction.displayName = "SidebarGroupAction"
485
-
486
- const SidebarGroupContent = React.forwardRef<
487
- HTMLDivElement,
488
- React.ComponentProps<"div">
489
- >(({ className, ...props }, ref) => (
490
- <div
491
- ref={ref}
492
- data-sidebar="group-content"
493
- className={cn("w-full text-sm", className)}
494
- {...props}
495
- />
496
- ))
497
- SidebarGroupContent.displayName = "SidebarGroupContent"
498
-
499
- const SidebarMenu = React.forwardRef<
500
- HTMLUListElement,
501
- React.ComponentProps<"ul">
502
- >(({ className, ...props }, ref) => (
503
- <ul
504
- ref={ref}
505
- data-sidebar="menu"
506
- className={cn("flex w-full min-w-0 flex-col gap-1", className)}
507
- {...props}
508
- />
509
- ))
510
- SidebarMenu.displayName = "SidebarMenu"
511
-
512
- const SidebarMenuItem = React.forwardRef<
513
- HTMLLIElement,
514
- React.ComponentProps<"li">
515
- >(({ className, ...props }, ref) => (
516
- <li
517
- ref={ref}
518
- data-sidebar="menu-item"
519
- className={cn("group/menu-item relative", className)}
520
- {...props}
521
- />
522
- ))
523
- SidebarMenuItem.displayName = "SidebarMenuItem"
438
+ }
439
+
440
+ function SidebarGroupContent({
441
+ className,
442
+ ...props
443
+ }: React.ComponentProps<"div">) {
444
+ return (
445
+ <div
446
+ data-slot="sidebar-group-content"
447
+ data-sidebar="group-content"
448
+ className={cn("w-full text-sm", className)}
449
+ {...props}
450
+ />
451
+ )
452
+ }
453
+
454
+ function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) {
455
+ return (
456
+ <ul
457
+ data-slot="sidebar-menu"
458
+ data-sidebar="menu"
459
+ className={cn("flex w-full min-w-0 flex-col gap-1", className)}
460
+ {...props}
461
+ />
462
+ )
463
+ }
464
+
465
+ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
466
+ return (
467
+ <li
468
+ data-slot="sidebar-menu-item"
469
+ data-sidebar="menu-item"
470
+ className={cn("group/menu-item relative", className)}
471
+ {...props}
472
+ />
473
+ )
474
+ }
524
475
 
525
476
  const sidebarMenuButtonVariants = cva(
526
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
477
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
527
478
  {
528
479
  variants: {
529
480
  variant: {
@@ -534,7 +485,7 @@ const sidebarMenuButtonVariants = cva(
534
485
  size: {
535
486
  default: "h-8 text-sm",
536
487
  sm: "h-7 text-xs",
537
- lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
488
+ lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
538
489
  },
539
490
  },
540
491
  defaultVariants: {
@@ -544,123 +495,117 @@ const sidebarMenuButtonVariants = cva(
544
495
  }
545
496
  )
546
497
 
547
- const SidebarMenuButton = React.forwardRef<
548
- HTMLButtonElement,
549
- React.ComponentProps<"button"> & {
550
- asChild?: boolean
551
- isActive?: boolean
552
- tooltip?: string | React.ComponentProps<typeof TooltipContent>
553
- } & VariantProps<typeof sidebarMenuButtonVariants>
554
- >(
555
- (
556
- {
557
- asChild = false,
558
- isActive = false,
559
- variant = "default",
560
- size = "default",
561
- tooltip,
562
- className,
563
- ...props
564
- },
565
- ref
566
- ) => {
567
- const Comp = asChild ? Slot : "button"
568
- const { isMobile, state } = useSidebar()
569
-
570
- const button = (
571
- <Comp
572
- ref={ref}
573
- data-sidebar="menu-button"
574
- data-size={size}
575
- data-active={isActive}
576
- className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
577
- {...props}
578
- />
579
- )
580
-
581
- if (!tooltip) {
582
- return button
583
- }
498
+ function SidebarMenuButton({
499
+ asChild = false,
500
+ isActive = false,
501
+ variant = "default",
502
+ size = "default",
503
+ tooltip,
504
+ className,
505
+ ...props
506
+ }: React.ComponentProps<"button"> & {
507
+ asChild?: boolean
508
+ isActive?: boolean
509
+ tooltip?: string | React.ComponentProps<typeof TooltipContent>
510
+ } & VariantProps<typeof sidebarMenuButtonVariants>) {
511
+ const Comp = asChild ? Slot : "button"
512
+ const { isMobile, state } = useSidebar()
584
513
 
585
- if (typeof tooltip === "string") {
586
- tooltip = {
587
- children: tooltip,
588
- }
589
- }
514
+ const button = (
515
+ <Comp
516
+ data-slot="sidebar-menu-button"
517
+ data-sidebar="menu-button"
518
+ data-size={size}
519
+ data-active={isActive}
520
+ className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
521
+ {...props}
522
+ />
523
+ )
590
524
 
591
- return (
592
- <Tooltip>
593
- <TooltipTrigger asChild>{button}</TooltipTrigger>
594
- <TooltipContent
595
- side="right"
596
- align="center"
597
- hidden={state !== "collapsed" || isMobile}
598
- {...tooltip}
599
- />
600
- </Tooltip>
601
- )
525
+ if (!tooltip) {
526
+ return button
602
527
  }
603
- )
604
- SidebarMenuButton.displayName = "SidebarMenuButton"
605
528
 
606
- const SidebarMenuAction = React.forwardRef<
607
- HTMLButtonElement,
608
- React.ComponentProps<"button"> & {
609
- asChild?: boolean
610
- showOnHover?: boolean
529
+ if (typeof tooltip === "string") {
530
+ tooltip = {
531
+ children: tooltip,
532
+ }
611
533
  }
612
- >(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
534
+
535
+ return (
536
+ <Tooltip>
537
+ <TooltipTrigger asChild>{button}</TooltipTrigger>
538
+ <TooltipContent
539
+ side="right"
540
+ align="center"
541
+ hidden={state !== "collapsed" || isMobile}
542
+ {...tooltip}
543
+ />
544
+ </Tooltip>
545
+ )
546
+ }
547
+
548
+ function SidebarMenuAction({
549
+ className,
550
+ asChild = false,
551
+ showOnHover = false,
552
+ ...props
553
+ }: React.ComponentProps<"button"> & {
554
+ asChild?: boolean
555
+ showOnHover?: boolean
556
+ }) {
613
557
  const Comp = asChild ? Slot : "button"
614
558
 
615
559
  return (
616
560
  <Comp
617
- ref={ref}
561
+ data-slot="sidebar-menu-action"
618
562
  data-sidebar="menu-action"
619
563
  className={cn(
620
- "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
564
+ "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
621
565
  // Increases the hit area of the button on mobile.
622
- "after:absolute after:-inset-2 after:md:hidden",
566
+ "after:absolute after:-inset-2 md:after:hidden",
623
567
  "peer-data-[size=sm]/menu-button:top-1",
624
568
  "peer-data-[size=default]/menu-button:top-1.5",
625
569
  "peer-data-[size=lg]/menu-button:top-2.5",
626
570
  "group-data-[collapsible=icon]:hidden",
627
571
  showOnHover &&
628
- "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
572
+ "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground data-[state=open]:opacity-100 md:opacity-0",
629
573
  className
630
574
  )}
631
575
  {...props}
632
576
  />
633
577
  )
634
- })
635
- SidebarMenuAction.displayName = "SidebarMenuAction"
636
-
637
- const SidebarMenuBadge = React.forwardRef<
638
- HTMLDivElement,
639
- React.ComponentProps<"div">
640
- >(({ className, ...props }, ref) => (
641
- <div
642
- ref={ref}
643
- data-sidebar="menu-badge"
644
- className={cn(
645
- "pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
646
- "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
647
- "peer-data-[size=sm]/menu-button:top-1",
648
- "peer-data-[size=default]/menu-button:top-1.5",
649
- "peer-data-[size=lg]/menu-button:top-2.5",
650
- "group-data-[collapsible=icon]:hidden",
651
- className
652
- )}
653
- {...props}
654
- />
655
- ))
656
- SidebarMenuBadge.displayName = "SidebarMenuBadge"
657
-
658
- const SidebarMenuSkeleton = React.forwardRef<
659
- HTMLDivElement,
660
- React.ComponentProps<"div"> & {
661
- showIcon?: boolean
662
- }
663
- >(({ className, showIcon = false, ...props }, ref) => {
578
+ }
579
+
580
+ function SidebarMenuBadge({
581
+ className,
582
+ ...props
583
+ }: React.ComponentProps<"div">) {
584
+ return (
585
+ <div
586
+ data-slot="sidebar-menu-badge"
587
+ data-sidebar="menu-badge"
588
+ className={cn(
589
+ "pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none",
590
+ "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
591
+ "peer-data-[size=sm]/menu-button:top-1",
592
+ "peer-data-[size=default]/menu-button:top-1.5",
593
+ "peer-data-[size=lg]/menu-button:top-2.5",
594
+ "group-data-[collapsible=icon]:hidden",
595
+ className
596
+ )}
597
+ {...props}
598
+ />
599
+ )
600
+ }
601
+
602
+ function SidebarMenuSkeleton({
603
+ className,
604
+ showIcon = false,
605
+ ...props
606
+ }: React.ComponentProps<"div"> & {
607
+ showIcon?: boolean
608
+ }) {
664
609
  // Random width between 50 to 90%.
665
610
  const width = React.useMemo(() => {
666
611
  return `${Math.floor(Math.random() * 40) + 50}%`
@@ -668,7 +613,7 @@ const SidebarMenuSkeleton = React.forwardRef<
668
613
 
669
614
  return (
670
615
  <div
671
- ref={ref}
616
+ data-slot="sidebar-menu-skeleton"
672
617
  data-sidebar="menu-skeleton"
673
618
  className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
674
619
  {...props}
@@ -680,7 +625,7 @@ const SidebarMenuSkeleton = React.forwardRef<
680
625
  />
681
626
  )}
682
627
  <Skeleton
683
- className="h-4 max-w-[--skeleton-width] flex-1"
628
+ className="h-4 max-w-(--skeleton-width) flex-1"
684
629
  data-sidebar="menu-skeleton-text"
685
630
  style={
686
631
  {
@@ -690,50 +635,58 @@ const SidebarMenuSkeleton = React.forwardRef<
690
635
  />
691
636
  </div>
692
637
  )
693
- })
694
- SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton"
695
-
696
- const SidebarMenuSub = React.forwardRef<
697
- HTMLUListElement,
698
- React.ComponentProps<"ul">
699
- >(({ className, ...props }, ref) => (
700
- <ul
701
- ref={ref}
702
- data-sidebar="menu-sub"
703
- className={cn(
704
- "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
705
- "group-data-[collapsible=icon]:hidden",
706
- className
707
- )}
708
- {...props}
709
- />
710
- ))
711
- SidebarMenuSub.displayName = "SidebarMenuSub"
712
-
713
- const SidebarMenuSubItem = React.forwardRef<
714
- HTMLLIElement,
715
- React.ComponentProps<"li">
716
- >(({ ...props }, ref) => <li ref={ref} {...props} />)
717
- SidebarMenuSubItem.displayName = "SidebarMenuSubItem"
718
-
719
- const SidebarMenuSubButton = React.forwardRef<
720
- HTMLAnchorElement,
721
- React.ComponentProps<"a"> & {
722
- asChild?: boolean
723
- size?: "sm" | "md"
724
- isActive?: boolean
725
- }
726
- >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
638
+ }
639
+
640
+ function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
641
+ return (
642
+ <ul
643
+ data-slot="sidebar-menu-sub"
644
+ data-sidebar="menu-sub"
645
+ className={cn(
646
+ "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
647
+ "group-data-[collapsible=icon]:hidden",
648
+ className
649
+ )}
650
+ {...props}
651
+ />
652
+ )
653
+ }
654
+
655
+ function SidebarMenuSubItem({
656
+ className,
657
+ ...props
658
+ }: React.ComponentProps<"li">) {
659
+ return (
660
+ <li
661
+ data-slot="sidebar-menu-sub-item"
662
+ data-sidebar="menu-sub-item"
663
+ className={cn("group/menu-sub-item relative", className)}
664
+ {...props}
665
+ />
666
+ )
667
+ }
668
+
669
+ function SidebarMenuSubButton({
670
+ asChild = false,
671
+ size = "md",
672
+ isActive = false,
673
+ className,
674
+ ...props
675
+ }: React.ComponentProps<"a"> & {
676
+ asChild?: boolean
677
+ size?: "sm" | "md"
678
+ isActive?: boolean
679
+ }) {
727
680
  const Comp = asChild ? Slot : "a"
728
681
 
729
682
  return (
730
683
  <Comp
731
- ref={ref}
684
+ data-slot="sidebar-menu-sub-button"
732
685
  data-sidebar="menu-sub-button"
733
686
  data-size={size}
734
687
  data-active={isActive}
735
688
  className={cn(
736
- "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
689
+ "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
737
690
  "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
738
691
  size === "sm" && "text-xs",
739
692
  size === "md" && "text-sm",
@@ -743,8 +696,7 @@ const SidebarMenuSubButton = React.forwardRef<
743
696
  {...props}
744
697
  />
745
698
  )
746
- })
747
- SidebarMenuSubButton.displayName = "SidebarMenuSubButton"
699
+ }
748
700
 
749
701
  export {
750
702
  Sidebar,