@kushagradhawan/kookie-ui 0.1.15 → 0.1.16
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/components.css +1321 -131
- package/dist/cjs/components/dropdown-menu.js +1 -1
- package/dist/cjs/components/dropdown-menu.js.map +2 -2
- package/dist/cjs/components/icons.d.ts +2 -1
- package/dist/cjs/components/icons.d.ts.map +1 -1
- package/dist/cjs/components/icons.js +1 -1
- package/dist/cjs/components/icons.js.map +3 -3
- package/dist/cjs/components/image.d.ts +4 -0
- package/dist/cjs/components/image.d.ts.map +1 -1
- package/dist/cjs/components/image.js +1 -1
- package/dist/cjs/components/image.js.map +3 -3
- package/dist/cjs/components/sidebar.d.ts +117 -42
- package/dist/cjs/components/sidebar.d.ts.map +1 -1
- package/dist/cjs/components/sidebar.js +1 -1
- package/dist/cjs/components/sidebar.js.map +3 -3
- package/dist/cjs/components/sidebar.props.d.ts +17 -10
- package/dist/cjs/components/sidebar.props.d.ts.map +1 -1
- package/dist/cjs/components/sidebar.props.js +1 -1
- package/dist/cjs/components/sidebar.props.js.map +3 -3
- package/dist/esm/components/dropdown-menu.js +1 -1
- package/dist/esm/components/dropdown-menu.js.map +3 -3
- package/dist/esm/components/icons.d.ts +2 -1
- package/dist/esm/components/icons.d.ts.map +1 -1
- package/dist/esm/components/icons.js +1 -1
- package/dist/esm/components/icons.js.map +3 -3
- package/dist/esm/components/image.d.ts +4 -0
- package/dist/esm/components/image.d.ts.map +1 -1
- package/dist/esm/components/image.js +1 -1
- package/dist/esm/components/image.js.map +3 -3
- package/dist/esm/components/sidebar.d.ts +117 -42
- package/dist/esm/components/sidebar.d.ts.map +1 -1
- package/dist/esm/components/sidebar.js +1 -1
- package/dist/esm/components/sidebar.js.map +3 -3
- package/dist/esm/components/sidebar.props.d.ts +17 -10
- package/dist/esm/components/sidebar.props.d.ts.map +1 -1
- package/dist/esm/components/sidebar.props.js +1 -1
- package/dist/esm/components/sidebar.props.js.map +3 -3
- package/package.json +1 -1
- package/src/components/_internal/base-button.css +2 -9
- package/src/components/_internal/base-menu.css +2 -2
- package/src/components/button.css +2 -2
- package/src/components/dropdown-menu.tsx +2 -2
- package/src/components/icon-button.css +2 -2
- package/src/components/icons.tsx +18 -1
- package/src/components/image.tsx +48 -9
- package/src/components/sidebar.css +850 -54
- package/src/components/sidebar.props.tsx +15 -11
- package/src/components/sidebar.tsx +500 -367
- package/styles.css +1321 -131
|
@@ -2,29 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
+
import { Slot } from './slot';
|
|
6
|
+
import { Accordion } from 'radix-ui';
|
|
5
7
|
|
|
6
|
-
import { sidebarPropDefs } from './sidebar.props
|
|
8
|
+
import { sidebarPropDefs } from './sidebar.props';
|
|
9
|
+
import { Theme, useThemeContext } from './theme';
|
|
10
|
+
import { IconButton } from './icon-button';
|
|
11
|
+
import { ScrollArea } from './scroll-area';
|
|
12
|
+
import { Separator } from './separator';
|
|
13
|
+
import { ChevronDownIcon, ThickChevronRightIcon } from './icons';
|
|
14
|
+
import { extractProps } from '../helpers/extract-props';
|
|
7
15
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { Separator } from './separator.js';
|
|
11
|
-
import { Theme, useThemeContext } from './theme.js';
|
|
12
|
-
import { ChevronDownIcon } from './icons.js';
|
|
13
|
-
import { extractProps } from '../helpers/extract-props.js';
|
|
16
|
+
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props';
|
|
17
|
+
import type { GetPropDefTypes } from '../props/prop-def';
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
// Import base menu styling and components
|
|
17
|
-
import { baseMenuItemPropDefs } from './_internal/base-menu.props.js';
|
|
18
|
-
import { Slot } from 'radix-ui';
|
|
19
|
-
|
|
20
|
-
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';
|
|
21
|
-
import type { GetPropDefTypes } from '../props/prop-def.js';
|
|
22
|
-
|
|
23
|
-
// Context for sidebar state
|
|
19
|
+
// Sidebar context for state management
|
|
24
20
|
type SidebarContextProps = {
|
|
21
|
+
state: 'expanded' | 'collapsed';
|
|
25
22
|
open: boolean;
|
|
26
23
|
setOpen: (open: boolean) => void;
|
|
27
|
-
|
|
24
|
+
openMobile: boolean;
|
|
25
|
+
setOpenMobile: (open: boolean) => void;
|
|
26
|
+
isMobile: boolean;
|
|
27
|
+
toggleSidebar: () => void;
|
|
28
|
+
side: 'left' | 'right';
|
|
29
|
+
type: 'sidebar' | 'floating';
|
|
30
|
+
variant: 'soft' | 'surface' | 'ghost';
|
|
31
|
+
menuVariant: 'solid' | 'soft';
|
|
32
|
+
collapsible: 'offcanvas' | 'icon' | 'none';
|
|
33
|
+
size: '1' | '2';
|
|
28
34
|
};
|
|
29
35
|
|
|
30
36
|
const SidebarContext = React.createContext<SidebarContextProps | null>(null);
|
|
@@ -32,37 +38,87 @@ const SidebarContext = React.createContext<SidebarContextProps | null>(null);
|
|
|
32
38
|
function useSidebar() {
|
|
33
39
|
const context = React.useContext(SidebarContext);
|
|
34
40
|
if (!context) {
|
|
35
|
-
throw new Error('useSidebar must be used within a
|
|
41
|
+
throw new Error('useSidebar must be used within a SidebarProvider.');
|
|
36
42
|
}
|
|
37
43
|
return context;
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
// Hook to detect mobile (simplified version)
|
|
47
|
+
function useIsMobile() {
|
|
48
|
+
const [isMobile, setIsMobile] = React.useState(false);
|
|
49
|
+
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
const checkIsMobile = () => {
|
|
52
|
+
setIsMobile(window.innerWidth < 768);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
checkIsMobile();
|
|
56
|
+
window.addEventListener('resize', checkIsMobile);
|
|
57
|
+
return () => window.removeEventListener('resize', checkIsMobile);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
return isMobile;
|
|
61
|
+
}
|
|
62
|
+
|
|
40
63
|
// Provider component
|
|
41
64
|
interface SidebarProviderProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
42
65
|
defaultOpen?: boolean;
|
|
43
66
|
open?: boolean;
|
|
44
67
|
onOpenChange?: (open: boolean) => void;
|
|
68
|
+
side?: 'left' | 'right';
|
|
45
69
|
}
|
|
46
70
|
|
|
47
71
|
const SidebarProvider = React.forwardRef<HTMLDivElement, SidebarProviderProps>(
|
|
48
|
-
({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, children, ...props }, forwardedRef) => {
|
|
72
|
+
({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, side = 'left', className, children, ...props }, forwardedRef) => {
|
|
73
|
+
const isMobile = useIsMobile();
|
|
74
|
+
const [openMobile, setOpenMobile] = React.useState(false);
|
|
75
|
+
|
|
49
76
|
// Internal state for uncontrolled mode
|
|
50
77
|
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
51
78
|
|
|
52
79
|
// Use controlled state if provided, otherwise internal state
|
|
53
80
|
const open = openProp ?? internalOpen;
|
|
54
81
|
|
|
55
|
-
const setOpen = React.useCallback((value: boolean) => {
|
|
82
|
+
const setOpen = React.useCallback((value: boolean | ((value: boolean) => boolean)) => {
|
|
83
|
+
const openState = typeof value === 'function' ? value(open) : value;
|
|
56
84
|
if (setOpenProp) {
|
|
57
|
-
setOpenProp(
|
|
85
|
+
setOpenProp(openState);
|
|
58
86
|
} else {
|
|
59
|
-
setInternalOpen(
|
|
87
|
+
setInternalOpen(openState);
|
|
60
88
|
}
|
|
61
|
-
}, [setOpenProp]);
|
|
89
|
+
}, [setOpenProp, open]);
|
|
90
|
+
|
|
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
|
+
// State for data attributes
|
|
97
|
+
const state = open ? 'expanded' : 'collapsed';
|
|
98
|
+
|
|
99
|
+
const contextValue = React.useMemo<Partial<SidebarContextProps>>(
|
|
100
|
+
() => ({
|
|
101
|
+
state,
|
|
102
|
+
open,
|
|
103
|
+
setOpen,
|
|
104
|
+
isMobile,
|
|
105
|
+
openMobile,
|
|
106
|
+
setOpenMobile,
|
|
107
|
+
toggleSidebar,
|
|
108
|
+
side,
|
|
109
|
+
}),
|
|
110
|
+
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar, side]
|
|
111
|
+
);
|
|
62
112
|
|
|
63
113
|
return (
|
|
64
|
-
<div
|
|
65
|
-
|
|
114
|
+
<div
|
|
115
|
+
{...props}
|
|
116
|
+
ref={forwardedRef}
|
|
117
|
+
className={classNames('rt-SidebarProvider', className)}
|
|
118
|
+
data-state={state}
|
|
119
|
+
data-side={side}
|
|
120
|
+
>
|
|
121
|
+
<SidebarContext.Provider value={contextValue as SidebarContextProps}>
|
|
66
122
|
{children}
|
|
67
123
|
</SidebarContext.Provider>
|
|
68
124
|
</div>
|
|
@@ -71,49 +127,112 @@ const SidebarProvider = React.forwardRef<HTMLDivElement, SidebarProviderProps>(
|
|
|
71
127
|
);
|
|
72
128
|
SidebarProvider.displayName = 'Sidebar.Provider';
|
|
73
129
|
|
|
74
|
-
//
|
|
75
|
-
type
|
|
76
|
-
|
|
77
|
-
interface SidebarRootProps
|
|
78
|
-
extends ComponentPropsWithout<'div', RemovedProps>,
|
|
79
|
-
SidebarRootOwnProps {}
|
|
130
|
+
// Main Sidebar component
|
|
131
|
+
type SidebarOwnProps = GetPropDefTypes<typeof sidebarPropDefs>;
|
|
132
|
+
interface SidebarProps extends ComponentPropsWithout<'div', RemovedProps>, SidebarOwnProps {}
|
|
80
133
|
|
|
81
|
-
const
|
|
134
|
+
const Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(
|
|
82
135
|
(props, forwardedRef) => {
|
|
83
136
|
const themeContext = useThemeContext();
|
|
84
|
-
const {
|
|
85
|
-
|
|
137
|
+
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
138
|
+
|
|
86
139
|
const {
|
|
87
140
|
size = sidebarPropDefs.size.default,
|
|
88
141
|
variant = sidebarPropDefs.variant.default,
|
|
142
|
+
menuVariant = sidebarPropDefs.menuVariant.default,
|
|
143
|
+
type = sidebarPropDefs.type.default,
|
|
89
144
|
side = sidebarPropDefs.side.default,
|
|
90
145
|
collapsible = sidebarPropDefs.collapsible.default,
|
|
91
|
-
floating: _floating = sidebarPropDefs.floating.default,
|
|
92
146
|
color,
|
|
93
147
|
highContrast = sidebarPropDefs.highContrast.default,
|
|
148
|
+
asChild,
|
|
94
149
|
} = props;
|
|
95
150
|
|
|
96
151
|
const { className, children, ...rootProps } = extractProps(props, sidebarPropDefs);
|
|
152
|
+
const { asChild: _, ...safeRootProps } = rootProps; // Remove asChild from DOM props
|
|
97
153
|
const resolvedColor = color || themeContext.accentColor;
|
|
98
154
|
|
|
155
|
+
// Update context with current props - we'll pass the resolved values
|
|
156
|
+
const resolvedSize = typeof size === 'object' ? size.initial || '2' : size;
|
|
157
|
+
const context = React.useContext(SidebarContext);
|
|
158
|
+
if (context) {
|
|
159
|
+
context.side = side;
|
|
160
|
+
context.type = type;
|
|
161
|
+
context.variant = variant;
|
|
162
|
+
context.menuVariant = menuVariant;
|
|
163
|
+
context.collapsible = collapsible;
|
|
164
|
+
context.size = resolvedSize;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (collapsible === 'none') {
|
|
168
|
+
return (
|
|
169
|
+
<div
|
|
170
|
+
{...safeRootProps}
|
|
171
|
+
ref={forwardedRef}
|
|
172
|
+
data-accent-color={resolvedColor}
|
|
173
|
+
data-state={state}
|
|
174
|
+
data-side={side}
|
|
175
|
+
data-type={type}
|
|
176
|
+
data-collapsible={collapsible}
|
|
177
|
+
className={classNames('rt-SidebarRoot', `rt-r-size-${size}`, className)}
|
|
178
|
+
>
|
|
179
|
+
<Theme>
|
|
180
|
+
<div
|
|
181
|
+
className={classNames('rt-SidebarContainer', `rt-variant-${variant}`)}
|
|
182
|
+
data-accent-color={resolvedColor}
|
|
183
|
+
data-high-contrast={highContrast || undefined}
|
|
184
|
+
data-side={side}
|
|
185
|
+
>
|
|
186
|
+
{children}
|
|
187
|
+
</div>
|
|
188
|
+
</Theme>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (isMobile) {
|
|
194
|
+
return (
|
|
195
|
+
<div
|
|
196
|
+
{...safeRootProps}
|
|
197
|
+
ref={forwardedRef}
|
|
198
|
+
data-accent-color={resolvedColor}
|
|
199
|
+
data-state={openMobile ? 'open' : 'closed'}
|
|
200
|
+
data-side={side}
|
|
201
|
+
data-type={type}
|
|
202
|
+
data-collapsible={collapsible}
|
|
203
|
+
className={classNames('rt-SidebarRoot', 'rt-SidebarRoot--mobile', className)}
|
|
204
|
+
>
|
|
205
|
+
<Theme>
|
|
206
|
+
<div
|
|
207
|
+
className={classNames('rt-SidebarContainer', `rt-variant-${variant}`, `rt-r-size-${size}`)}
|
|
208
|
+
data-accent-color={resolvedColor}
|
|
209
|
+
data-high-contrast={highContrast || undefined}
|
|
210
|
+
data-side={side}
|
|
211
|
+
>
|
|
212
|
+
{children}
|
|
213
|
+
</div>
|
|
214
|
+
</Theme>
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
99
219
|
return (
|
|
100
220
|
<div
|
|
101
|
-
{...
|
|
221
|
+
{...safeRootProps}
|
|
102
222
|
ref={forwardedRef}
|
|
103
223
|
data-accent-color={resolvedColor}
|
|
104
|
-
data-state={
|
|
224
|
+
data-state={state}
|
|
105
225
|
data-side={side}
|
|
226
|
+
data-type={type}
|
|
106
227
|
data-collapsible={collapsible}
|
|
107
|
-
className={classNames(
|
|
108
|
-
'rt-SidebarRoot',
|
|
109
|
-
className
|
|
110
|
-
)}
|
|
228
|
+
className={classNames('rt-SidebarRoot', className)}
|
|
111
229
|
>
|
|
112
|
-
<Theme
|
|
230
|
+
<Theme>
|
|
113
231
|
<div
|
|
114
232
|
className={classNames('rt-SidebarContainer', `rt-variant-${variant}`, `rt-r-size-${size}`)}
|
|
115
233
|
data-accent-color={resolvedColor}
|
|
116
234
|
data-high-contrast={highContrast || undefined}
|
|
235
|
+
data-side={side}
|
|
117
236
|
>
|
|
118
237
|
{children}
|
|
119
238
|
</div>
|
|
@@ -122,415 +241,429 @@ const SidebarRoot = React.forwardRef<SidebarRootElement, SidebarRootProps>(
|
|
|
122
241
|
);
|
|
123
242
|
}
|
|
124
243
|
);
|
|
125
|
-
|
|
244
|
+
Sidebar.displayName = 'Sidebar.Root';
|
|
126
245
|
|
|
127
246
|
// Sidebar content area
|
|
128
|
-
|
|
129
|
-
interface SidebarContentProps extends ComponentPropsWithout<'div', RemovedProps> {}
|
|
247
|
+
interface SidebarContentProps extends React.ComponentPropsWithoutRef<'div'> {}
|
|
130
248
|
|
|
131
|
-
const SidebarContent = React.forwardRef<
|
|
132
|
-
({ className, children, ...props }, forwardedRef) =>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
249
|
+
const SidebarContent = React.forwardRef<HTMLDivElement, SidebarContentProps>(
|
|
250
|
+
({ className, children, ...props }, forwardedRef) => {
|
|
251
|
+
const context = React.useContext(SidebarContext);
|
|
252
|
+
const { size = '2', menuVariant = 'soft' } = context || {};
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<ScrollArea type="auto">
|
|
256
|
+
<div
|
|
257
|
+
{...props}
|
|
258
|
+
ref={forwardedRef}
|
|
259
|
+
className={classNames(
|
|
260
|
+
'rt-SidebarContent',
|
|
261
|
+
`rt-r-size-${size}`,
|
|
262
|
+
`rt-menu-variant-${menuVariant}`,
|
|
263
|
+
className
|
|
264
|
+
)}
|
|
265
|
+
>
|
|
266
|
+
{children}
|
|
267
|
+
</div>
|
|
268
|
+
</ScrollArea>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
143
271
|
);
|
|
144
272
|
SidebarContent.displayName = 'Sidebar.Content';
|
|
145
273
|
|
|
146
274
|
// Sidebar header
|
|
147
|
-
|
|
148
|
-
|
|
275
|
+
interface SidebarHeaderProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
276
|
+
/**
|
|
277
|
+
* Whether to use the default flex container layout.
|
|
278
|
+
* @default true
|
|
279
|
+
*/
|
|
280
|
+
asContainer?: boolean;
|
|
281
|
+
}
|
|
149
282
|
|
|
150
|
-
const SidebarHeader = React.forwardRef<
|
|
151
|
-
({ className, ...props }, forwardedRef) =>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
283
|
+
const SidebarHeader = React.forwardRef<HTMLDivElement, SidebarHeaderProps>(
|
|
284
|
+
({ className, asContainer = true, ...props }, forwardedRef) => {
|
|
285
|
+
const context = React.useContext(SidebarContext);
|
|
286
|
+
const { size = '2', menuVariant = 'soft' } = context || {};
|
|
287
|
+
|
|
288
|
+
return (
|
|
289
|
+
<div
|
|
290
|
+
{...props}
|
|
291
|
+
ref={forwardedRef}
|
|
292
|
+
className={classNames(
|
|
293
|
+
'rt-SidebarHeader',
|
|
294
|
+
`rt-r-size-${size}`,
|
|
295
|
+
`rt-menu-variant-${menuVariant}`,
|
|
296
|
+
{
|
|
297
|
+
'rt-SidebarHeader--container': asContainer,
|
|
298
|
+
},
|
|
299
|
+
className
|
|
300
|
+
)}
|
|
301
|
+
/>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
158
304
|
);
|
|
159
305
|
SidebarHeader.displayName = 'Sidebar.Header';
|
|
160
306
|
|
|
161
307
|
// Sidebar footer
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
ref={forwardedRef}
|
|
170
|
-
className={classNames('rt-SidebarFooter', 'rt-BaseMenuContent', className)}
|
|
171
|
-
/>
|
|
172
|
-
)
|
|
173
|
-
);
|
|
174
|
-
SidebarFooter.displayName = 'Sidebar.Footer';
|
|
175
|
-
|
|
176
|
-
// Sidebar trigger button
|
|
177
|
-
type SidebarTriggerElement = React.ElementRef<typeof IconButton>;
|
|
178
|
-
interface SidebarTriggerProps extends ComponentPropsWithout<typeof IconButton, RemovedProps> {}
|
|
308
|
+
interface SidebarFooterProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
309
|
+
/**
|
|
310
|
+
* Whether to use the default flex container layout.
|
|
311
|
+
* @default true
|
|
312
|
+
*/
|
|
313
|
+
asContainer?: boolean;
|
|
314
|
+
}
|
|
179
315
|
|
|
180
|
-
const
|
|
181
|
-
({
|
|
182
|
-
const
|
|
316
|
+
const SidebarFooter = React.forwardRef<HTMLDivElement, SidebarFooterProps>(
|
|
317
|
+
({ className, asContainer = true, ...props }, forwardedRef) => {
|
|
318
|
+
const context = React.useContext(SidebarContext);
|
|
319
|
+
const { size = '2', menuVariant = 'soft' } = context || {};
|
|
183
320
|
|
|
184
321
|
return (
|
|
185
|
-
<
|
|
322
|
+
<div
|
|
186
323
|
{...props}
|
|
187
324
|
ref={forwardedRef}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
325
|
+
className={classNames(
|
|
326
|
+
'rt-SidebarFooter',
|
|
327
|
+
`rt-r-size-${size}`,
|
|
328
|
+
`rt-menu-variant-${menuVariant}`,
|
|
329
|
+
{
|
|
330
|
+
'rt-SidebarFooter--container': asContainer,
|
|
331
|
+
},
|
|
332
|
+
className
|
|
333
|
+
)}
|
|
334
|
+
/>
|
|
196
335
|
);
|
|
197
336
|
}
|
|
198
337
|
);
|
|
338
|
+
SidebarFooter.displayName = 'Sidebar.Footer';
|
|
339
|
+
|
|
340
|
+
// Sidebar trigger button
|
|
341
|
+
interface SidebarTriggerProps extends ComponentPropsWithout<typeof IconButton, RemovedProps> {}
|
|
342
|
+
|
|
343
|
+
const SidebarTrigger = React.forwardRef<
|
|
344
|
+
React.ElementRef<typeof IconButton>,
|
|
345
|
+
SidebarTriggerProps
|
|
346
|
+
>(({ onClick, children, ...props }, forwardedRef) => {
|
|
347
|
+
const { toggleSidebar } = useSidebar();
|
|
348
|
+
|
|
349
|
+
return (
|
|
350
|
+
<IconButton
|
|
351
|
+
{...props}
|
|
352
|
+
ref={forwardedRef}
|
|
353
|
+
variant="ghost"
|
|
354
|
+
onClick={(event) => {
|
|
355
|
+
onClick?.(event);
|
|
356
|
+
toggleSidebar();
|
|
357
|
+
}}
|
|
358
|
+
>
|
|
359
|
+
{children || <ChevronDownIcon />}
|
|
360
|
+
</IconButton>
|
|
361
|
+
);
|
|
362
|
+
});
|
|
199
363
|
SidebarTrigger.displayName = 'Sidebar.Trigger';
|
|
200
364
|
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
|
|
365
|
+
// Removed SidebarInset - not needed
|
|
366
|
+
|
|
367
|
+
// Sidebar separator
|
|
368
|
+
interface SidebarSeparatorProps extends ComponentPropsWithout<typeof Separator, RemovedProps> {}
|
|
369
|
+
|
|
370
|
+
const SidebarSeparator = React.forwardRef<
|
|
371
|
+
React.ComponentRef<typeof Separator>,
|
|
372
|
+
SidebarSeparatorProps
|
|
373
|
+
>(({ className, ...props }, forwardedRef) => (
|
|
374
|
+
<Separator
|
|
375
|
+
{...props}
|
|
376
|
+
ref={forwardedRef}
|
|
377
|
+
className={classNames('rt-SidebarSeparator', className)}
|
|
378
|
+
/>
|
|
379
|
+
));
|
|
380
|
+
SidebarSeparator.displayName = 'Sidebar.Separator';
|
|
204
381
|
|
|
205
|
-
|
|
382
|
+
// Menu components - reusing dropdown menu structure
|
|
383
|
+
interface SidebarMenuProps extends React.ComponentPropsWithoutRef<'ul'> {}
|
|
384
|
+
|
|
385
|
+
const SidebarMenu = React.forwardRef<HTMLUListElement, SidebarMenuProps>(
|
|
206
386
|
({ className, ...props }, forwardedRef) => (
|
|
207
|
-
<
|
|
387
|
+
<ul
|
|
208
388
|
{...props}
|
|
209
389
|
ref={forwardedRef}
|
|
210
|
-
className={classNames('rt-
|
|
390
|
+
className={classNames('rt-SidebarMenu', className)}
|
|
211
391
|
/>
|
|
212
392
|
)
|
|
213
393
|
);
|
|
214
|
-
|
|
394
|
+
SidebarMenu.displayName = 'Sidebar.Menu';
|
|
215
395
|
|
|
216
|
-
|
|
217
|
-
interface SidebarLabelProps extends React.ComponentPropsWithoutRef<'div'> {}
|
|
396
|
+
interface SidebarMenuItemProps extends React.ComponentPropsWithoutRef<'li'> {}
|
|
218
397
|
|
|
219
|
-
const
|
|
220
|
-
({ className, ...props },
|
|
221
|
-
<
|
|
222
|
-
ref={ref}
|
|
223
|
-
className={classNames('rt-BaseMenuLabel', className)}
|
|
398
|
+
const SidebarMenuItem = React.forwardRef<HTMLLIElement, SidebarMenuItemProps>(
|
|
399
|
+
({ className, ...props }, forwardedRef) => (
|
|
400
|
+
<li
|
|
224
401
|
{...props}
|
|
402
|
+
ref={forwardedRef}
|
|
403
|
+
className={classNames('rt-SidebarMenuItem', className)}
|
|
225
404
|
/>
|
|
226
405
|
)
|
|
227
406
|
);
|
|
228
|
-
|
|
407
|
+
SidebarMenuItem.displayName = 'Sidebar.MenuItem';
|
|
229
408
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
409
|
+
interface SidebarMenuButtonProps extends React.ComponentPropsWithoutRef<'button'> {
|
|
410
|
+
asChild?: boolean;
|
|
411
|
+
isActive?: boolean;
|
|
412
|
+
}
|
|
234
413
|
|
|
235
|
-
const
|
|
236
|
-
(props,
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
children,
|
|
240
|
-
color = baseMenuItemPropDefs.color.default,
|
|
241
|
-
shortcut,
|
|
242
|
-
asChild = false,
|
|
243
|
-
onMouseEnter,
|
|
244
|
-
onMouseLeave,
|
|
245
|
-
onFocus,
|
|
246
|
-
onBlur,
|
|
247
|
-
...itemProps
|
|
248
|
-
} = props;
|
|
249
|
-
|
|
250
|
-
const [highlighted, setHighlighted] = React.useState(false);
|
|
251
|
-
|
|
252
|
-
const handleMouseEnter = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
253
|
-
setHighlighted(true);
|
|
254
|
-
onMouseEnter?.(e);
|
|
255
|
-
}, [onMouseEnter]);
|
|
256
|
-
|
|
257
|
-
const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
258
|
-
setHighlighted(false);
|
|
259
|
-
onMouseLeave?.(e);
|
|
260
|
-
}, [onMouseLeave]);
|
|
261
|
-
|
|
262
|
-
const handleFocus = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
263
|
-
setHighlighted(true);
|
|
264
|
-
onFocus?.(e);
|
|
265
|
-
}, [onFocus]);
|
|
266
|
-
|
|
267
|
-
const handleBlur = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
268
|
-
setHighlighted(false);
|
|
269
|
-
onBlur?.(e);
|
|
270
|
-
}, [onBlur]);
|
|
271
|
-
|
|
272
|
-
if (asChild) {
|
|
273
|
-
return (
|
|
274
|
-
<Slot.Root
|
|
275
|
-
ref={ref}
|
|
276
|
-
data-accent-color={color}
|
|
277
|
-
data-highlighted={highlighted || undefined}
|
|
278
|
-
className={classNames('rt-reset', 'rt-BaseMenuItem', className)}
|
|
279
|
-
onMouseEnter={handleMouseEnter}
|
|
280
|
-
onMouseLeave={handleMouseLeave}
|
|
281
|
-
onFocus={handleFocus}
|
|
282
|
-
onBlur={handleBlur}
|
|
283
|
-
{...itemProps}
|
|
284
|
-
>
|
|
285
|
-
{children}
|
|
286
|
-
</Slot.Root>
|
|
287
|
-
);
|
|
288
|
-
}
|
|
414
|
+
const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenuButtonProps>(
|
|
415
|
+
({ asChild = false, isActive = false, className, onMouseEnter, onMouseLeave, ...props }, forwardedRef) => {
|
|
416
|
+
const [isHighlighted, setIsHighlighted] = React.useState(false);
|
|
417
|
+
const Comp = asChild ? Slot : 'button';
|
|
289
418
|
|
|
290
419
|
return (
|
|
291
|
-
<
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
{
|
|
420
|
+
<Comp
|
|
421
|
+
{...props}
|
|
422
|
+
ref={forwardedRef}
|
|
423
|
+
className={classNames(
|
|
424
|
+
'rt-reset',
|
|
425
|
+
'rt-SidebarMenuButton',
|
|
426
|
+
className
|
|
427
|
+
)}
|
|
428
|
+
data-active={isActive || undefined}
|
|
429
|
+
data-highlighted={isHighlighted || undefined}
|
|
430
|
+
onMouseEnter={(event) => {
|
|
431
|
+
setIsHighlighted(true);
|
|
432
|
+
onMouseEnter?.(event);
|
|
433
|
+
}}
|
|
434
|
+
onMouseLeave={(event) => {
|
|
435
|
+
setIsHighlighted(false);
|
|
436
|
+
onMouseLeave?.(event);
|
|
437
|
+
}}
|
|
438
|
+
/>
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
SidebarMenuButton.displayName = 'Sidebar.MenuButton';
|
|
443
|
+
|
|
444
|
+
// Sub-menu components using Radix Accordion
|
|
445
|
+
interface SidebarMenuSubProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
446
|
+
defaultOpen?: boolean;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const SidebarMenuSub = React.forwardRef<HTMLDivElement, SidebarMenuSubProps>(
|
|
450
|
+
({ defaultOpen = false, children, ...props }, forwardedRef) => {
|
|
451
|
+
return (
|
|
452
|
+
<div {...props} ref={forwardedRef}>
|
|
453
|
+
<Accordion.Root
|
|
454
|
+
type="single"
|
|
455
|
+
collapsible
|
|
456
|
+
defaultValue={defaultOpen ? 'item' : undefined}
|
|
457
|
+
>
|
|
458
|
+
<Accordion.Item value="item">
|
|
459
|
+
{children}
|
|
460
|
+
</Accordion.Item>
|
|
461
|
+
</Accordion.Root>
|
|
306
462
|
</div>
|
|
307
463
|
);
|
|
308
464
|
}
|
|
309
465
|
);
|
|
310
|
-
|
|
466
|
+
SidebarMenuSub.displayName = 'Sidebar.MenuSub';
|
|
467
|
+
|
|
468
|
+
interface SidebarMenuSubTriggerProps extends React.ComponentPropsWithoutRef<typeof Accordion.Trigger> {
|
|
469
|
+
asChild?: boolean;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
const SidebarMenuSubTrigger = React.forwardRef<
|
|
473
|
+
React.ElementRef<typeof Accordion.Trigger>,
|
|
474
|
+
SidebarMenuSubTriggerProps
|
|
475
|
+
>(({ asChild = false, className, children, onMouseEnter, onMouseLeave, ...props }, forwardedRef) => {
|
|
476
|
+
const [isHighlighted, setIsHighlighted] = React.useState(false);
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
<Accordion.Header asChild>
|
|
480
|
+
<div>
|
|
481
|
+
<Accordion.Trigger
|
|
482
|
+
{...props}
|
|
483
|
+
ref={forwardedRef}
|
|
484
|
+
asChild={asChild}
|
|
485
|
+
className={classNames(
|
|
486
|
+
'rt-reset',
|
|
487
|
+
'rt-SidebarMenuButton',
|
|
488
|
+
'rt-SidebarMenuSubTrigger',
|
|
489
|
+
className
|
|
490
|
+
)}
|
|
491
|
+
data-highlighted={isHighlighted || undefined}
|
|
492
|
+
onMouseEnter={(event) => {
|
|
493
|
+
setIsHighlighted(true);
|
|
494
|
+
onMouseEnter?.(event);
|
|
495
|
+
}}
|
|
496
|
+
onMouseLeave={(event) => {
|
|
497
|
+
setIsHighlighted(false);
|
|
498
|
+
onMouseLeave?.(event);
|
|
499
|
+
}}
|
|
500
|
+
>
|
|
501
|
+
{asChild ? (
|
|
502
|
+
children
|
|
503
|
+
) : (
|
|
504
|
+
<>
|
|
505
|
+
{children}
|
|
506
|
+
<ThickChevronRightIcon
|
|
507
|
+
className={classNames(
|
|
508
|
+
'rt-BaseMenuSubTriggerIcon',
|
|
509
|
+
'rt-SidebarMenuSubTriggerIcon'
|
|
510
|
+
)}
|
|
511
|
+
/>
|
|
512
|
+
</>
|
|
513
|
+
)}
|
|
514
|
+
</Accordion.Trigger>
|
|
515
|
+
</div>
|
|
516
|
+
</Accordion.Header>
|
|
517
|
+
);
|
|
518
|
+
});
|
|
519
|
+
SidebarMenuSubTrigger.displayName = 'Sidebar.MenuSubTrigger';
|
|
520
|
+
|
|
521
|
+
interface SidebarMenuSubContentProps extends React.ComponentPropsWithoutRef<typeof Accordion.Content> {}
|
|
522
|
+
|
|
523
|
+
const SidebarMenuSubContent = React.forwardRef<
|
|
524
|
+
React.ElementRef<typeof Accordion.Content>,
|
|
525
|
+
SidebarMenuSubContentProps
|
|
526
|
+
>(({ className, children, ...props }, forwardedRef) => {
|
|
527
|
+
return (
|
|
528
|
+
<Accordion.Content
|
|
529
|
+
{...props}
|
|
530
|
+
ref={forwardedRef}
|
|
531
|
+
className={classNames('rt-SidebarMenuSubContent', className)}
|
|
532
|
+
>
|
|
533
|
+
<div className="rt-SidebarMenuSubList">
|
|
534
|
+
{children}
|
|
535
|
+
</div>
|
|
536
|
+
</Accordion.Content>
|
|
537
|
+
);
|
|
538
|
+
});
|
|
539
|
+
SidebarMenuSubContent.displayName = 'Sidebar.MenuSubContent';
|
|
311
540
|
|
|
541
|
+
// Group components
|
|
312
542
|
interface SidebarGroupProps extends React.ComponentPropsWithoutRef<'div'> {}
|
|
313
543
|
|
|
314
544
|
const SidebarGroup = React.forwardRef<HTMLDivElement, SidebarGroupProps>(
|
|
315
|
-
({ className, ...props },
|
|
545
|
+
({ className, ...props }, forwardedRef) => (
|
|
316
546
|
<div
|
|
317
|
-
ref={ref}
|
|
318
|
-
className={classNames('rt-BaseMenuGroup', className)}
|
|
319
547
|
{...props}
|
|
548
|
+
ref={forwardedRef}
|
|
549
|
+
className={classNames('rt-SidebarGroup', className)}
|
|
320
550
|
/>
|
|
321
551
|
)
|
|
322
552
|
);
|
|
323
553
|
SidebarGroup.displayName = 'Sidebar.Group';
|
|
324
554
|
|
|
325
|
-
interface
|
|
326
|
-
|
|
327
|
-
const SidebarSeparator = React.forwardRef<HTMLDivElement, SidebarSeparatorProps>(
|
|
328
|
-
({ className, ..._props }, ref) => (
|
|
329
|
-
<Separator
|
|
330
|
-
ref={ref}
|
|
331
|
-
className={classNames('rt-BaseMenuSeparator', className)}
|
|
332
|
-
/>
|
|
333
|
-
)
|
|
334
|
-
);
|
|
335
|
-
SidebarSeparator.displayName = 'Sidebar.Separator';
|
|
336
|
-
|
|
337
|
-
// Sidebar checkbox item with proper prop filtering
|
|
338
|
-
interface SidebarCheckboxItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
339
|
-
checked?: boolean;
|
|
340
|
-
onCheckedChange?: (checked: boolean) => void;
|
|
341
|
-
color?: string;
|
|
342
|
-
shortcut?: string;
|
|
555
|
+
interface SidebarGroupLabelProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
556
|
+
asChild?: boolean;
|
|
343
557
|
}
|
|
344
558
|
|
|
345
|
-
const
|
|
346
|
-
({
|
|
347
|
-
|
|
348
|
-
checked,
|
|
349
|
-
onCheckedChange,
|
|
350
|
-
children,
|
|
351
|
-
color,
|
|
352
|
-
shortcut,
|
|
353
|
-
onMouseEnter,
|
|
354
|
-
onMouseLeave,
|
|
355
|
-
onFocus,
|
|
356
|
-
onBlur,
|
|
357
|
-
onClick,
|
|
358
|
-
...props
|
|
359
|
-
}, ref) => {
|
|
360
|
-
const [highlighted, setHighlighted] = React.useState(false);
|
|
361
|
-
|
|
362
|
-
const handleMouseEnter = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
363
|
-
setHighlighted(true);
|
|
364
|
-
onMouseEnter?.(e);
|
|
365
|
-
}, [onMouseEnter]);
|
|
366
|
-
|
|
367
|
-
const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
368
|
-
setHighlighted(false);
|
|
369
|
-
onMouseLeave?.(e);
|
|
370
|
-
}, [onMouseLeave]);
|
|
371
|
-
|
|
372
|
-
const handleFocus = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
373
|
-
setHighlighted(true);
|
|
374
|
-
onFocus?.(e);
|
|
375
|
-
}, [onFocus]);
|
|
376
|
-
|
|
377
|
-
const handleBlur = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
378
|
-
setHighlighted(false);
|
|
379
|
-
onBlur?.(e);
|
|
380
|
-
}, [onBlur]);
|
|
381
|
-
|
|
382
|
-
const handleClick = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
383
|
-
onCheckedChange?.(!checked);
|
|
384
|
-
onClick?.(e);
|
|
385
|
-
}, [checked, onCheckedChange, onClick]);
|
|
559
|
+
const SidebarGroupLabel = React.forwardRef<HTMLDivElement, SidebarGroupLabelProps>(
|
|
560
|
+
({ asChild = false, className, ...props }, forwardedRef) => {
|
|
561
|
+
const Comp = asChild ? Slot : 'div';
|
|
386
562
|
|
|
387
563
|
return (
|
|
388
|
-
<
|
|
389
|
-
ref={ref}
|
|
390
|
-
data-accent-color={color}
|
|
391
|
-
data-highlighted={highlighted || undefined}
|
|
392
|
-
className={classNames(
|
|
393
|
-
'rt-reset',
|
|
394
|
-
'rt-BaseMenuItem',
|
|
395
|
-
'rt-BaseMenuCheckboxItem',
|
|
396
|
-
className
|
|
397
|
-
)}
|
|
398
|
-
onClick={handleClick}
|
|
399
|
-
onKeyDown={(e) => {
|
|
400
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
401
|
-
e.preventDefault();
|
|
402
|
-
handleClick(e as any);
|
|
403
|
-
}
|
|
404
|
-
}}
|
|
405
|
-
onMouseEnter={handleMouseEnter}
|
|
406
|
-
onMouseLeave={handleMouseLeave}
|
|
407
|
-
onFocus={handleFocus}
|
|
408
|
-
onBlur={handleBlur}
|
|
409
|
-
tabIndex={0}
|
|
410
|
-
role="menuitemcheckbox"
|
|
411
|
-
aria-checked={checked}
|
|
564
|
+
<Comp
|
|
412
565
|
{...props}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
{shortcut && <div className="rt-BaseMenuShortcut">{shortcut}</div>}
|
|
417
|
-
</div>
|
|
566
|
+
ref={forwardedRef}
|
|
567
|
+
className={classNames('rt-SidebarGroupLabel', className)}
|
|
568
|
+
/>
|
|
418
569
|
);
|
|
419
570
|
}
|
|
420
571
|
);
|
|
421
|
-
|
|
572
|
+
SidebarGroupLabel.displayName = 'Sidebar.GroupLabel';
|
|
422
573
|
|
|
423
|
-
|
|
424
|
-
interface SidebarRadioGroupProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
425
|
-
value?: string;
|
|
426
|
-
onValueChange?: (value: string) => void;
|
|
427
|
-
}
|
|
574
|
+
interface SidebarGroupContentProps extends React.ComponentPropsWithoutRef<'div'> {}
|
|
428
575
|
|
|
429
|
-
const
|
|
430
|
-
({ className,
|
|
576
|
+
const SidebarGroupContent = React.forwardRef<HTMLDivElement, SidebarGroupContentProps>(
|
|
577
|
+
({ className, ...props }, forwardedRef) => (
|
|
431
578
|
<div
|
|
432
|
-
ref={ref}
|
|
433
|
-
className={classNames('rt-BaseMenuGroup', className)}
|
|
434
579
|
{...props}
|
|
435
|
-
|
|
436
|
-
{
|
|
437
|
-
|
|
580
|
+
ref={forwardedRef}
|
|
581
|
+
className={classNames('rt-SidebarGroupContent', className)}
|
|
582
|
+
/>
|
|
438
583
|
)
|
|
439
584
|
);
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
// Sidebar radio item with proper prop filtering
|
|
443
|
-
interface SidebarRadioItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
444
|
-
value?: string;
|
|
445
|
-
color?: string;
|
|
446
|
-
shortcut?: string;
|
|
447
|
-
}
|
|
585
|
+
SidebarGroupContent.displayName = 'Sidebar.GroupContent';
|
|
448
586
|
|
|
449
|
-
|
|
450
|
-
({
|
|
451
|
-
className,
|
|
452
|
-
value,
|
|
453
|
-
children,
|
|
454
|
-
color,
|
|
455
|
-
shortcut,
|
|
456
|
-
onMouseEnter,
|
|
457
|
-
onMouseLeave,
|
|
458
|
-
onFocus,
|
|
459
|
-
onBlur,
|
|
460
|
-
...props
|
|
461
|
-
}, ref) => {
|
|
462
|
-
const [highlighted, setHighlighted] = React.useState(false);
|
|
463
|
-
|
|
464
|
-
const handleMouseEnter = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
465
|
-
setHighlighted(true);
|
|
466
|
-
onMouseEnter?.(e);
|
|
467
|
-
}, [onMouseEnter]);
|
|
468
|
-
|
|
469
|
-
const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
|
470
|
-
setHighlighted(false);
|
|
471
|
-
onMouseLeave?.(e);
|
|
472
|
-
}, [onMouseLeave]);
|
|
473
|
-
|
|
474
|
-
const handleFocus = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
475
|
-
setHighlighted(true);
|
|
476
|
-
onFocus?.(e);
|
|
477
|
-
}, [onFocus]);
|
|
478
|
-
|
|
479
|
-
const handleBlur = React.useCallback((e: React.FocusEvent<HTMLDivElement>) => {
|
|
480
|
-
setHighlighted(false);
|
|
481
|
-
onBlur?.(e);
|
|
482
|
-
}, [onBlur]);
|
|
483
|
-
|
|
484
|
-
return (
|
|
485
|
-
<div
|
|
486
|
-
ref={ref}
|
|
487
|
-
data-accent-color={color}
|
|
488
|
-
data-highlighted={highlighted || undefined}
|
|
489
|
-
className={classNames('rt-reset', 'rt-BaseMenuItem', className)}
|
|
490
|
-
onMouseEnter={handleMouseEnter}
|
|
491
|
-
onMouseLeave={handleMouseLeave}
|
|
492
|
-
onFocus={handleFocus}
|
|
493
|
-
onBlur={handleBlur}
|
|
494
|
-
tabIndex={0}
|
|
495
|
-
role="menuitemradio"
|
|
496
|
-
aria-checked={false}
|
|
497
|
-
{...props}
|
|
498
|
-
>
|
|
499
|
-
<Slot.Slottable>{children}</Slot.Slottable>
|
|
500
|
-
{shortcut && <div className="rt-BaseMenuShortcut">{shortcut}</div>}
|
|
501
|
-
</div>
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
);
|
|
505
|
-
SidebarRadioItem.displayName = 'Sidebar.RadioItem';
|
|
506
|
-
|
|
507
|
-
// Export all components
|
|
587
|
+
// Export all components following shadcn's pattern
|
|
508
588
|
export {
|
|
509
589
|
SidebarProvider as Provider,
|
|
510
|
-
|
|
590
|
+
Sidebar as Root,
|
|
511
591
|
SidebarContent as Content,
|
|
512
592
|
SidebarHeader as Header,
|
|
513
593
|
SidebarFooter as Footer,
|
|
514
594
|
SidebarTrigger as Trigger,
|
|
515
|
-
SidebarInset as Inset,
|
|
516
|
-
// Re-export DropdownMenu components as sidebar menu components
|
|
517
|
-
SidebarLabel as Label,
|
|
518
|
-
SidebarItem as Item,
|
|
519
|
-
SidebarGroup as Group,
|
|
520
595
|
SidebarSeparator as Separator,
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
596
|
+
SidebarMenu as Menu,
|
|
597
|
+
SidebarMenuItem as MenuItem,
|
|
598
|
+
SidebarMenuButton as MenuButton,
|
|
599
|
+
SidebarMenuSub as MenuSub,
|
|
600
|
+
SidebarMenuSubTrigger as MenuSubTrigger,
|
|
601
|
+
SidebarMenuSubContent as MenuSubContent,
|
|
602
|
+
SidebarGroup as Group,
|
|
603
|
+
SidebarGroupLabel as GroupLabel,
|
|
604
|
+
SidebarGroupContent as GroupContent,
|
|
524
605
|
// Export hook
|
|
525
606
|
useSidebar,
|
|
526
607
|
};
|
|
527
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Enhanced Sidebar Header and Footer Usage Examples:
|
|
611
|
+
*
|
|
612
|
+
* 1. Simple default container (backwards compatible):
|
|
613
|
+
* <Sidebar.Header>
|
|
614
|
+
* <Logo />
|
|
615
|
+
* <span>App Name</span>
|
|
616
|
+
* </Sidebar.Header>
|
|
617
|
+
*
|
|
618
|
+
* 2. Custom flex layout:
|
|
619
|
+
* <Sidebar.Header className="rt-justify-between rt-gap-3">
|
|
620
|
+
* <Logo />
|
|
621
|
+
* <Sidebar.MenuButton>
|
|
622
|
+
* <SettingsIcon />
|
|
623
|
+
* </Sidebar.MenuButton>
|
|
624
|
+
* </Sidebar.Header>
|
|
625
|
+
*
|
|
626
|
+
* 3. Column layout for multiple rows:
|
|
627
|
+
* <Sidebar.Header className="rt-flex-col rt-gap-2" asContainer={false}>
|
|
628
|
+
* <div className="rt-flex rt-items-center rt-gap-2">
|
|
629
|
+
* <Logo />
|
|
630
|
+
* <span>App Name</span>
|
|
631
|
+
* </div>
|
|
632
|
+
* <Sidebar.MenuButton>
|
|
633
|
+
* <UserAvatar />
|
|
634
|
+
* <span>John Doe</span>
|
|
635
|
+
* </Sidebar.MenuButton>
|
|
636
|
+
* </Sidebar.Header>
|
|
637
|
+
*
|
|
638
|
+
* 4. Interactive footer with menu button:
|
|
639
|
+
* <Sidebar.Footer>
|
|
640
|
+
* <Sidebar.MenuButton>
|
|
641
|
+
* <UserIcon />
|
|
642
|
+
* <span>Settings</span>
|
|
643
|
+
* <ChevronUpIcon />
|
|
644
|
+
* </Sidebar.MenuButton>
|
|
645
|
+
* </Sidebar.Footer>
|
|
646
|
+
*
|
|
647
|
+
* 5. Custom footer layout:
|
|
648
|
+
* <Sidebar.Footer className="rt-justify-between">
|
|
649
|
+
* <span>v1.0.0</span>
|
|
650
|
+
* <Sidebar.MenuButton>
|
|
651
|
+
* <HelpIcon />
|
|
652
|
+
* </Sidebar.MenuButton>
|
|
653
|
+
* </Sidebar.Footer>
|
|
654
|
+
*
|
|
655
|
+
* Available utility classes:
|
|
656
|
+
* - Layout: rt-flex-row, rt-flex-col
|
|
657
|
+
* - Alignment: rt-items-center, rt-items-start, rt-items-end
|
|
658
|
+
* - Justification: rt-justify-between, rt-justify-center, rt-justify-start, rt-justify-end
|
|
659
|
+
* - Gap: rt-gap-1, rt-gap-2, rt-gap-3, rt-gap-4
|
|
660
|
+
*/
|
|
661
|
+
|
|
528
662
|
export type {
|
|
529
663
|
SidebarProviderProps as ProviderProps,
|
|
530
|
-
|
|
664
|
+
SidebarProps as RootProps,
|
|
531
665
|
SidebarContentProps as ContentProps,
|
|
532
666
|
SidebarHeaderProps as HeaderProps,
|
|
533
667
|
SidebarFooterProps as FooterProps,
|
|
534
668
|
SidebarTriggerProps as TriggerProps,
|
|
535
|
-
SidebarInsetProps as InsetProps,
|
|
536
669
|
};
|