@sikka/hawa 0.1.17 → 0.1.20
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/README.md +2 -16
- package/dist/styles.css +78 -3
- package/es/elements/Button.d.ts +1 -1
- package/es/elements/HawaRadio.d.ts +1 -0
- package/es/elements/InterfaceSettings.d.ts +2 -0
- package/es/elements/Popover.d.ts +1 -0
- package/es/index.es.js +3 -3
- package/es/layout/AppLayout.d.ts +49 -0
- package/es/layout/Sidebar.d.ts +36 -0
- package/es/layout/Sidebar2.d.ts +20 -0
- package/es/layout/index.d.ts +2 -0
- package/lib/elements/Button.d.ts +1 -1
- package/lib/elements/HawaRadio.d.ts +1 -0
- package/lib/elements/InterfaceSettings.d.ts +2 -0
- package/lib/elements/Popover.d.ts +1 -0
- package/lib/index.js +3 -3
- package/lib/layout/AppLayout.d.ts +49 -0
- package/lib/layout/Sidebar.d.ts +36 -0
- package/lib/layout/Sidebar2.d.ts +20 -0
- package/lib/layout/index.d.ts +2 -0
- package/package.json +2 -1
- package/src/blocks/AuthForms/SignInBlock.tsx +0 -2
- package/src/blocks/AuthForms/SignInForm.tsx +1 -1
- package/src/elements/Button.tsx +1 -0
- package/src/elements/DropdownMenu.tsx +0 -2
- package/src/elements/HawaRadio.tsx +8 -2
- package/src/elements/InterfaceSettings.tsx +15 -2
- package/src/elements/Label.tsx +0 -2
- package/src/elements/Popover.tsx +28 -22
- package/src/elements/Select.tsx +0 -2
- package/src/elements/Tooltip.tsx +1 -106
- package/src/layout/AppLayout.tsx +445 -0
- package/src/layout/HawaAppLayoutSimplified.tsx +78 -98
- package/src/layout/Sidebar.tsx +224 -0
- package/src/layout/Sidebar2.tsx +77 -0
- package/src/layout/index.ts +3 -0
- package/src/styles.css +78 -3
- package/tailwind.config.js +20 -1
|
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from "react"
|
|
|
2
2
|
import clsx from "clsx"
|
|
3
3
|
import useDiscloser from "../hooks/useDiscloser"
|
|
4
4
|
import useBreakpoint from "../hooks/useBreakpoint"
|
|
5
|
-
import { Button, DropdownMenu,
|
|
5
|
+
import { Button, DropdownMenu, Tooltip } from "../elements"
|
|
6
6
|
|
|
7
7
|
type HawaAppLayoutTypes = {
|
|
8
8
|
/** The pages of the side drawer */
|
|
@@ -39,19 +39,13 @@ type SubItem = {
|
|
|
39
39
|
value: string
|
|
40
40
|
highlighted?: boolean
|
|
41
41
|
}
|
|
42
|
-
|
|
43
42
|
type Item = {
|
|
44
43
|
label: string
|
|
45
44
|
value: string
|
|
46
45
|
highlighted?: boolean
|
|
47
46
|
subitems?: SubItem[] // Note the use of the optional modifier
|
|
48
47
|
}
|
|
49
|
-
|
|
50
|
-
// icon?: JSX.Element
|
|
51
|
-
// label: string
|
|
52
|
-
// action?: (e: any) => void
|
|
53
|
-
// isButton?: boolean
|
|
54
|
-
// }
|
|
48
|
+
|
|
55
49
|
export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
56
50
|
HawaAppLayoutTypes
|
|
57
51
|
> = ({
|
|
@@ -195,18 +189,6 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
195
189
|
</div>
|
|
196
190
|
) : null}
|
|
197
191
|
{/* Profile Icon & Menu */}
|
|
198
|
-
{/* <HawaMenu
|
|
199
|
-
direction={direction}
|
|
200
|
-
withHeader={size > 600 ? false : true}
|
|
201
|
-
headerTitle={size > 600 ? "" : props.username}
|
|
202
|
-
headerSubtitle={size > 600 ? "" : props.email}
|
|
203
|
-
menuItems={props.profileMenuItems}
|
|
204
|
-
position={"bottom-left"}
|
|
205
|
-
>
|
|
206
|
-
<div className="relative mx-2 h-8 w-8 cursor-pointer overflow-hidden rounded-full ring-1 ring-buttonPrimary-500 dark:bg-gray-600">
|
|
207
|
-
<AvatarIcon />
|
|
208
|
-
</div>
|
|
209
|
-
</HawaMenu> */}
|
|
210
192
|
<DropdownMenu
|
|
211
193
|
triggerClassname="mx-2"
|
|
212
194
|
align="end"
|
|
@@ -221,11 +203,15 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
221
203
|
}
|
|
222
204
|
items={props.profileMenuItems}
|
|
223
205
|
onItemSelect={(e) => console.log("selecting item ", e)}
|
|
224
|
-
/>
|
|
206
|
+
/>
|
|
225
207
|
</div>
|
|
226
208
|
</div>
|
|
227
209
|
)}
|
|
228
|
-
{/*
|
|
210
|
+
{/*
|
|
211
|
+
* ----------------------------------------------------------------------------------------------------
|
|
212
|
+
* Drawer Container
|
|
213
|
+
* ----------------------------------------------------------------------------------------------------
|
|
214
|
+
*/}
|
|
229
215
|
<div
|
|
230
216
|
className={clsx(
|
|
231
217
|
"fixed top-0 z-40 flex h-full flex-col justify-between overflow-x-clip transition-all",
|
|
@@ -249,7 +235,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
249
235
|
}
|
|
250
236
|
ref={ref}
|
|
251
237
|
>
|
|
252
|
-
{/*
|
|
238
|
+
{/*
|
|
239
|
+
* ----------------------------------------------------------------------------------------------------
|
|
240
|
+
* Drawer Header
|
|
241
|
+
* ----------------------------------------------------------------------------------------------------
|
|
242
|
+
*/}
|
|
253
243
|
<div
|
|
254
244
|
dir={direction}
|
|
255
245
|
className={clsx(
|
|
@@ -262,7 +252,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
262
252
|
: `${openSideMenu ? openDrawerWidth : 0}px`,
|
|
263
253
|
}}
|
|
264
254
|
>
|
|
265
|
-
{/*
|
|
255
|
+
{/*
|
|
256
|
+
* ----------------------------------------------------------------------------------------------------
|
|
257
|
+
* Full Logo
|
|
258
|
+
* ----------------------------------------------------------------------------------------------------
|
|
259
|
+
*/}
|
|
266
260
|
<img
|
|
267
261
|
className={clsx(
|
|
268
262
|
"h-9 opacity-0 transition-all",
|
|
@@ -277,8 +271,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
277
271
|
// )}
|
|
278
272
|
src={props.logoLink}
|
|
279
273
|
/>
|
|
280
|
-
|
|
281
|
-
|
|
274
|
+
{/*
|
|
275
|
+
* ----------------------------------------------------------------------------------------------------
|
|
276
|
+
* Logo Symbol
|
|
277
|
+
* ----------------------------------------------------------------------------------------------------
|
|
278
|
+
*/}
|
|
282
279
|
{size > 600 ? (
|
|
283
280
|
<img
|
|
284
281
|
className={clsx(
|
|
@@ -290,7 +287,11 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
290
287
|
/>
|
|
291
288
|
) : null}
|
|
292
289
|
</div>
|
|
293
|
-
{/*
|
|
290
|
+
{/*
|
|
291
|
+
* ----------------------------------------------------------------------------------------------------
|
|
292
|
+
* Drawer Content Container
|
|
293
|
+
* ----------------------------------------------------------------------------------------------------
|
|
294
|
+
*/}
|
|
294
295
|
<div
|
|
295
296
|
className={clsx(
|
|
296
297
|
// "no-scrollbar", TODO: make this optional to hide scrollbar or not
|
|
@@ -306,7 +307,12 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
306
307
|
: `${openSideMenu ? openDrawerWidth : 0}px`,
|
|
307
308
|
}}
|
|
308
309
|
>
|
|
309
|
-
{/*
|
|
310
|
+
{/*
|
|
311
|
+
* ----------------------------------------------------------------------------------------------------
|
|
312
|
+
* Drawer Items
|
|
313
|
+
* ----------------------------------------------------------------------------------------------------
|
|
314
|
+
*/}
|
|
315
|
+
|
|
310
316
|
{props.drawerItems?.map((dSection, dIndex) => (
|
|
311
317
|
<div
|
|
312
318
|
key={dIndex}
|
|
@@ -419,16 +425,19 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
419
425
|
)
|
|
420
426
|
})}
|
|
421
427
|
{dIndex !== props.drawerItems.length - 1 && (
|
|
422
|
-
<div className="my-2 h-[1px] w-10/12 self-center bg-buttonPrimary-500 text-center "></div>
|
|
428
|
+
<div className="my-2 h-[1px] w-10/12 self-center bg-buttonPrimary-500 bg-red-500 text-center "></div>
|
|
423
429
|
)}
|
|
424
430
|
</div>
|
|
425
431
|
))}
|
|
426
432
|
</div>
|
|
427
|
-
{/*
|
|
433
|
+
{/*
|
|
434
|
+
* ----------------------------------------------------------------------------------------------------
|
|
435
|
+
* Drawer Footer
|
|
436
|
+
* ----------------------------------------------------------------------------------------------------
|
|
437
|
+
*/}
|
|
428
438
|
<div
|
|
429
439
|
className={clsx(
|
|
430
|
-
"fixed bottom-0
|
|
431
|
-
|
|
440
|
+
"fixed bottom-0 flex h-14 w-full items-center justify-center gap-2 overflow-clip bg-primary-foreground transition-all",
|
|
432
441
|
direction === "rtl" ? "flex-row-reverse" : "flex-row"
|
|
433
442
|
)}
|
|
434
443
|
style={{
|
|
@@ -438,85 +447,56 @@ export const HawaAppLayoutSimplified: React.FunctionComponent<
|
|
|
438
447
|
: `${openSideMenu ? openDrawerWidth : 0}px`,
|
|
439
448
|
}}
|
|
440
449
|
>
|
|
441
|
-
{
|
|
450
|
+
{DrawerFooterActions && openSideMenu ? (
|
|
442
451
|
<>{DrawerFooterActions}</>
|
|
443
452
|
) : null}
|
|
444
453
|
|
|
445
454
|
{/* Expand Button */}
|
|
446
455
|
{size > 600 && openSideMenu ? (
|
|
447
|
-
<
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
drawerSize
|
|
455
|
-
] - 35
|
|
456
|
-
}px`,
|
|
457
|
-
}
|
|
458
|
-
: {
|
|
459
|
-
left: `${
|
|
460
|
-
drawerSizeStyle[openSideMenu ? "opened" : "closed"][
|
|
461
|
-
drawerSize
|
|
462
|
-
] - 35
|
|
463
|
-
}px`,
|
|
464
|
-
}
|
|
456
|
+
<Tooltip
|
|
457
|
+
side={"left"}
|
|
458
|
+
delayDuration={500}
|
|
459
|
+
content={
|
|
460
|
+
keepOpen
|
|
461
|
+
? props.texts?.collapseSidebar || "Collapse Sidebar"
|
|
462
|
+
: props.texts?.expandSidebar || "Expand Sidebar"
|
|
465
463
|
}
|
|
466
464
|
>
|
|
467
|
-
<
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
openSideMenu ? " opacity-100" : " opacity-0"
|
|
472
|
-
)}
|
|
465
|
+
<Button
|
|
466
|
+
variant="light"
|
|
467
|
+
onClick={() => setKeepOpen(!keepOpen)}
|
|
468
|
+
size="smallIcon"
|
|
473
469
|
>
|
|
474
|
-
<
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
content={
|
|
470
|
+
<svg
|
|
471
|
+
className={clsx(
|
|
472
|
+
"h-6 w-6 shrink-0 text-primary transition-all disabled:bg-gray-200 ",
|
|
478
473
|
keepOpen
|
|
479
|
-
?
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
474
|
+
? isRTL
|
|
475
|
+
? "-rotate-90"
|
|
476
|
+
: "rotate-90"
|
|
477
|
+
: isRTL
|
|
478
|
+
? "rotate-90"
|
|
479
|
+
: "-rotate-90"
|
|
480
|
+
)}
|
|
481
|
+
fill="currentColor"
|
|
482
|
+
viewBox="0 0 20 20"
|
|
483
483
|
>
|
|
484
|
-
<
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
>
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
// directionStyle
|
|
493
|
-
keepOpen
|
|
494
|
-
? isRTL
|
|
495
|
-
? "-rotate-90"
|
|
496
|
-
: "rotate-90"
|
|
497
|
-
: isRTL
|
|
498
|
-
? "rotate-90"
|
|
499
|
-
: "-rotate-90"
|
|
500
|
-
)}
|
|
501
|
-
fill="currentColor"
|
|
502
|
-
viewBox="0 0 20 20"
|
|
503
|
-
>
|
|
504
|
-
<path
|
|
505
|
-
fillRule="evenodd"
|
|
506
|
-
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
|
507
|
-
clipRule="evenodd"
|
|
508
|
-
></path>
|
|
509
|
-
</svg>
|
|
510
|
-
</Button>
|
|
511
|
-
</Tooltip>
|
|
512
|
-
</div>
|
|
513
|
-
</div>
|
|
484
|
+
<path
|
|
485
|
+
fillRule="evenodd"
|
|
486
|
+
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
|
487
|
+
clipRule="evenodd"
|
|
488
|
+
></path>
|
|
489
|
+
</svg>
|
|
490
|
+
</Button>
|
|
491
|
+
</Tooltip>
|
|
514
492
|
) : null}
|
|
515
493
|
</div>
|
|
516
494
|
</div>
|
|
517
|
-
{/*
|
|
518
|
-
|
|
519
|
-
|
|
495
|
+
{/*
|
|
496
|
+
* ----------------------------------------------------------------------------------------------------
|
|
497
|
+
* Children Container
|
|
498
|
+
* ----------------------------------------------------------------------------------------------------
|
|
499
|
+
*/}
|
|
520
500
|
<div
|
|
521
501
|
className="fixed overflow-y-auto"
|
|
522
502
|
style={
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../util"
|
|
5
|
+
|
|
6
|
+
const Accordion = AccordionPrimitive.Root
|
|
7
|
+
|
|
8
|
+
let triggerStyles =
|
|
9
|
+
"flex flex-1 items-center cursor-pointer bg-primary-foreground rounded justify-between p-2 px-3 font-medium transition-all [&[data-state=open]>svg]:-rotate-90"
|
|
10
|
+
const AccordionItem = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
|
13
|
+
>(({ className, ...props }, ref) => (
|
|
14
|
+
<AccordionPrimitive.Item ref={ref} className={cn(className)} {...props} />
|
|
15
|
+
))
|
|
16
|
+
AccordionItem.displayName = "AccordionItem"
|
|
17
|
+
|
|
18
|
+
const AccordionTrigger = React.forwardRef<
|
|
19
|
+
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
20
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
21
|
+
>(({ className, children, ...props }, ref) => (
|
|
22
|
+
<AccordionPrimitive.Header className="flex">
|
|
23
|
+
<AccordionPrimitive.Trigger
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn(triggerStyles, className)}
|
|
26
|
+
{...props}
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
<svg
|
|
30
|
+
aria-label="Chevron Right Icon"
|
|
31
|
+
stroke="currentColor"
|
|
32
|
+
fill="currentColor"
|
|
33
|
+
stroke-width="1"
|
|
34
|
+
viewBox="0 0 16 16"
|
|
35
|
+
height="1em"
|
|
36
|
+
width="1em"
|
|
37
|
+
className="h-4 w-4 shrink-0 rotate-90 transition-transform duration-200"
|
|
38
|
+
>
|
|
39
|
+
<path
|
|
40
|
+
fill-rule="evenodd"
|
|
41
|
+
d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"
|
|
42
|
+
></path>
|
|
43
|
+
</svg>
|
|
44
|
+
</AccordionPrimitive.Trigger>
|
|
45
|
+
</AccordionPrimitive.Header>
|
|
46
|
+
))
|
|
47
|
+
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
|
48
|
+
|
|
49
|
+
const AccordionContent = React.forwardRef<
|
|
50
|
+
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
51
|
+
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
52
|
+
>(({ className, children, ...props }, ref) => (
|
|
53
|
+
<AccordionPrimitive.Content
|
|
54
|
+
ref={ref}
|
|
55
|
+
className={cn(
|
|
56
|
+
"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
<div>{children}</div>
|
|
62
|
+
</AccordionPrimitive.Content>
|
|
63
|
+
))
|
|
64
|
+
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
|
65
|
+
|
|
66
|
+
type Item = {
|
|
67
|
+
value: string
|
|
68
|
+
label: string
|
|
69
|
+
icon?: any
|
|
70
|
+
subitems?: SubItem[]
|
|
71
|
+
onClick?: () => void
|
|
72
|
+
}
|
|
73
|
+
type SubItem = {
|
|
74
|
+
value: string
|
|
75
|
+
label: string
|
|
76
|
+
icon?: any
|
|
77
|
+
onClick?: () => void
|
|
78
|
+
}
|
|
79
|
+
interface SidebarGroupProps {
|
|
80
|
+
title?: string
|
|
81
|
+
items: Item[]
|
|
82
|
+
collapsed?: any
|
|
83
|
+
selectedItem?: any
|
|
84
|
+
isOpen?: boolean
|
|
85
|
+
onItemClick?: (value: string[]) => void
|
|
86
|
+
onSubItemClick?: (values: string[]) => void
|
|
87
|
+
}
|
|
88
|
+
interface SidebarRootProps {
|
|
89
|
+
children: any
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const SidebarRoot: React.FC<SidebarRootProps> = ({ children }) => (
|
|
93
|
+
<div className="flex flex-col gap-2">{children}</div>
|
|
94
|
+
)
|
|
95
|
+
const SidebarGroup: React.FC<SidebarGroupProps> = ({
|
|
96
|
+
title,
|
|
97
|
+
items,
|
|
98
|
+
selectedItem,
|
|
99
|
+
collapsed,
|
|
100
|
+
onItemClick,
|
|
101
|
+
onSubItemClick,
|
|
102
|
+
isOpen,
|
|
103
|
+
}) => {
|
|
104
|
+
React.useEffect(() => {
|
|
105
|
+
if (collapsed) {
|
|
106
|
+
// Logic to close all groups
|
|
107
|
+
}
|
|
108
|
+
}, [collapsed])
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div>
|
|
112
|
+
{title && <h3 className="mb-1 font-bold">{title}</h3>}
|
|
113
|
+
<ul className="flex flex-col gap-2">
|
|
114
|
+
<Accordion
|
|
115
|
+
type="single"
|
|
116
|
+
// defaultValue="item-1"
|
|
117
|
+
collapsible
|
|
118
|
+
className="flex flex-col gap-1"
|
|
119
|
+
>
|
|
120
|
+
{items.map((item, idx) => (
|
|
121
|
+
<SidebarItem
|
|
122
|
+
isOpen={isOpen}
|
|
123
|
+
isSelected={selectedItem}
|
|
124
|
+
key={idx}
|
|
125
|
+
item={item}
|
|
126
|
+
onItemClick={onItemClick}
|
|
127
|
+
onSubItemClick={onSubItemClick}
|
|
128
|
+
/>
|
|
129
|
+
))}
|
|
130
|
+
</Accordion>
|
|
131
|
+
</ul>
|
|
132
|
+
</div>
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
const SidebarItem: React.FC<{
|
|
136
|
+
item: Item
|
|
137
|
+
isSelected: any
|
|
138
|
+
onItemClick?: (value: string[]) => void
|
|
139
|
+
onSubItemClick?: (values: string[]) => void
|
|
140
|
+
isOpen?: boolean
|
|
141
|
+
}> = ({ item, isSelected, onItemClick, onSubItemClick, isOpen = true }) => {
|
|
142
|
+
const getSelectedStyle = (value: string, index: number) => {
|
|
143
|
+
return isSelected && isSelected[index] === value
|
|
144
|
+
? "bg-primary text-primary-foreground cursor-default"
|
|
145
|
+
: ""
|
|
146
|
+
}
|
|
147
|
+
if (item.subitems) {
|
|
148
|
+
return (
|
|
149
|
+
<AccordionItem value={item.value} className="overflow-x-clip">
|
|
150
|
+
<AccordionTrigger
|
|
151
|
+
className={cn(getSelectedStyle(item.value, 0), "hover:bg-primary/30")}
|
|
152
|
+
>
|
|
153
|
+
<div className={"flex flex-row items-center gap-2 "}>
|
|
154
|
+
{item.icon}
|
|
155
|
+
{/* {isOpen ? item.label : ""} */}
|
|
156
|
+
|
|
157
|
+
<span
|
|
158
|
+
className={cn(
|
|
159
|
+
"transition-all",
|
|
160
|
+
isOpen ? "opacity-100" : "opacity-0"
|
|
161
|
+
)}
|
|
162
|
+
>
|
|
163
|
+
{item.label}
|
|
164
|
+
</span>
|
|
165
|
+
</div>
|
|
166
|
+
</AccordionTrigger>
|
|
167
|
+
{item.subitems && (
|
|
168
|
+
<AccordionContent className=" mt-1 h-full rounded ">
|
|
169
|
+
<div
|
|
170
|
+
className={cn("flex h-full flex-col gap-2 bg-foreground/5 p-1")}
|
|
171
|
+
>
|
|
172
|
+
{item.subitems.map((subitem, idx) => (
|
|
173
|
+
<li
|
|
174
|
+
onClick={(e) => {
|
|
175
|
+
e.stopPropagation()
|
|
176
|
+
if (onSubItemClick) {
|
|
177
|
+
onSubItemClick([item.value, subitem.value])
|
|
178
|
+
}
|
|
179
|
+
}}
|
|
180
|
+
className={cn(
|
|
181
|
+
"flex h-full cursor-pointer flex-row items-center gap-2 rounded bg-foreground/10 p-2 transition-all hover:bg-foreground/30",
|
|
182
|
+
getSelectedStyle(subitem.value, 1)
|
|
183
|
+
)}
|
|
184
|
+
key={idx}
|
|
185
|
+
>
|
|
186
|
+
{subitem.icon}
|
|
187
|
+
{subitem.label}
|
|
188
|
+
</li>
|
|
189
|
+
))}
|
|
190
|
+
</div>
|
|
191
|
+
</AccordionContent>
|
|
192
|
+
)}
|
|
193
|
+
</AccordionItem>
|
|
194
|
+
)
|
|
195
|
+
} else {
|
|
196
|
+
return (
|
|
197
|
+
<div
|
|
198
|
+
onClick={() => {
|
|
199
|
+
if (onItemClick) {
|
|
200
|
+
onItemClick([item.value])
|
|
201
|
+
}
|
|
202
|
+
}}
|
|
203
|
+
className={cn(
|
|
204
|
+
triggerStyles,
|
|
205
|
+
getSelectedStyle(item.value, 0),
|
|
206
|
+
"overflow-x-clip hover:bg-primary/30"
|
|
207
|
+
)}
|
|
208
|
+
>
|
|
209
|
+
<div className={"flex flex-row items-center gap-2 "}>
|
|
210
|
+
{item.icon}
|
|
211
|
+
<span
|
|
212
|
+
className={cn(
|
|
213
|
+
"transition-all",
|
|
214
|
+
isOpen ? "opacity-100" : "opacity-0"
|
|
215
|
+
)}
|
|
216
|
+
>
|
|
217
|
+
{item.label}
|
|
218
|
+
</span>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
export { SidebarRoot, SidebarGroup, SidebarItem }
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AccordionItem,
|
|
3
|
+
AccordionTrigger,
|
|
4
|
+
AccordionContent,
|
|
5
|
+
Accordion,
|
|
6
|
+
} from "@radix-ui/react-accordion"
|
|
7
|
+
import React from "react"
|
|
8
|
+
import { cn } from "../util"
|
|
9
|
+
|
|
10
|
+
type Item = {
|
|
11
|
+
value: string
|
|
12
|
+
label: string
|
|
13
|
+
icon?: any
|
|
14
|
+
subitems?: Item[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface SidebarGroupProps {
|
|
18
|
+
title: string
|
|
19
|
+
items: Item[]
|
|
20
|
+
}
|
|
21
|
+
interface SidebarRootProps {
|
|
22
|
+
children: any
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const SidebarRoot: React.FC<SidebarRootProps> = ({ children }) => (
|
|
26
|
+
<div className="flex flex-col gap-2 rounded bg-red-200 p-2">{children}</div>
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const SidebarGroup: React.FC<SidebarGroupProps> = ({ title, items }) => (
|
|
30
|
+
<div>
|
|
31
|
+
<h3 className="mb-1 font-bold">{title}</h3>
|
|
32
|
+
<ul className="flex flex-col gap-2">
|
|
33
|
+
{items.map((item, idx) => (
|
|
34
|
+
<SidebarItem key={idx} item={item} />
|
|
35
|
+
))}
|
|
36
|
+
</ul>
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const SidebarItem: React.FC<{ item: Item }> = ({ item }) => (
|
|
41
|
+
// <li className="rounded bg-red-400 p-2">
|
|
42
|
+
<Accordion
|
|
43
|
+
// className="bg-mauve6 w-[300px] rounded-md shadow-[0_2px_10px] shadow-black/5"
|
|
44
|
+
type="single"
|
|
45
|
+
defaultValue="item-1"
|
|
46
|
+
collapsible
|
|
47
|
+
>
|
|
48
|
+
<AccordionItem value={item.value}>
|
|
49
|
+
<AccordionTrigger
|
|
50
|
+
className={cn()
|
|
51
|
+
// "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
|
52
|
+
// className
|
|
53
|
+
}
|
|
54
|
+
>
|
|
55
|
+
<div className="flex flex-row items-center gap-2">
|
|
56
|
+
{item.icon}
|
|
57
|
+
{item.label}
|
|
58
|
+
</div>
|
|
59
|
+
</AccordionTrigger>
|
|
60
|
+
|
|
61
|
+
{item.subitems && (
|
|
62
|
+
<AccordionContent
|
|
63
|
+
// className="flex flex-col gap-1 bg-blue-400"
|
|
64
|
+
>
|
|
65
|
+
{item.subitems.map((subitem, idx) => (
|
|
66
|
+
<li className="rounded bg-yellow-300 p-1" key={idx}>
|
|
67
|
+
{subitem.label}
|
|
68
|
+
</li>
|
|
69
|
+
))}
|
|
70
|
+
</AccordionContent>
|
|
71
|
+
)}
|
|
72
|
+
</AccordionItem>
|
|
73
|
+
</Accordion>
|
|
74
|
+
// </li>
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
export { SidebarRoot, SidebarGroup, SidebarItem }
|
package/src/layout/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./Box"
|
|
2
2
|
export * from "./HawaBottomAppBar"
|
|
3
3
|
export * from "./HawaSiteLayout"
|
|
4
|
+
export * from "./AppLayout"
|
|
4
5
|
export * from "./HawaAppLayout"
|
|
5
6
|
export * from "./HawaAppLayoutSimplified"
|
|
6
7
|
export * from "./HawaContainer"
|
|
@@ -8,3 +9,5 @@ export * from "./HawaGrid"
|
|
|
8
9
|
export * from "./AppSidebar"
|
|
9
10
|
export * from "./Footer"
|
|
10
11
|
export * from "./Banner"
|
|
12
|
+
// export * from "./Sidebar2"
|
|
13
|
+
export * from "./Sidebar"
|