aboutsummaryrefslogtreecommitdiff
path: root/src/components/common/SideMenu.tsx
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/components/common/SideMenu.tsx
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/components/common/SideMenu.tsx')
-rw-r--r--src/components/common/SideMenu.tsx80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/components/common/SideMenu.tsx b/src/components/common/SideMenu.tsx
new file mode 100644
index 0000000..92ff798
--- /dev/null
+++ b/src/components/common/SideMenu.tsx
@@ -0,0 +1,80 @@
+import {
+ Column,
+ Heading,
+ IconLabel,
+ NavMenu,
+ NavMenuGroup,
+ NavMenuItem,
+ type NavMenuProps,
+ Row,
+} from '@umami/react-zen';
+import Link from 'next/link';
+
+interface SideMenuData {
+ id: string;
+ label: string;
+ icon?: any;
+ path: string;
+}
+
+interface SideMenuItems {
+ label?: string;
+ items: SideMenuData[];
+}
+
+export interface SideMenuProps extends NavMenuProps {
+ items: SideMenuItems[];
+ title?: string;
+ selectedKey?: string;
+ allowMinimize?: boolean;
+}
+
+export function SideMenu({
+ items = [],
+ title,
+ selectedKey,
+ allowMinimize,
+ ...props
+}: SideMenuProps) {
+ const renderItems = (items: SideMenuData[]) => {
+ return items?.map(({ id, label, icon, path }) => {
+ const isSelected = selectedKey === id;
+
+ return (
+ <Link key={id} href={path}>
+ <NavMenuItem isSelected={isSelected}>
+ <IconLabel icon={icon}>{label}</IconLabel>
+ </NavMenuItem>
+ </Link>
+ );
+ });
+ };
+
+ return (
+ <Column gap overflowY="auto" justifyContent="space-between" position="sticky" top="20px">
+ {title && (
+ <Row padding>
+ <Heading size="1">{title}</Heading>
+ </Row>
+ )}
+ <NavMenu gap="6" {...props}>
+ {items?.map(({ label, items }, index) => {
+ if (label) {
+ return (
+ <NavMenuGroup
+ title={label}
+ key={`${label}${index}`}
+ gap="1"
+ allowMinimize={allowMinimize}
+ marginBottom="3"
+ >
+ {renderItems(items)}
+ </NavMenuGroup>
+ );
+ }
+ return null;
+ })}
+ </NavMenu>
+ </Column>
+ );
+}