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