mirror of
https://codeberg.org/MarkusThielker/next-ory.git
synced 2025-04-10 11:58:41 +00:00
NORY-34: rework app sidebar to support multiple groups
This commit is contained in:
parent
6d853ec309
commit
c9ebf95dd5
1 changed files with 105 additions and 30 deletions
|
@ -5,14 +5,13 @@ import {
|
||||||
SidebarContent,
|
SidebarContent,
|
||||||
SidebarFooter,
|
SidebarFooter,
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
|
||||||
SidebarGroupLabel,
|
SidebarGroupLabel,
|
||||||
SidebarMenu,
|
SidebarMenu,
|
||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
|
useSidebar,
|
||||||
} from '@/components/ui/sidebar';
|
} from '@/components/ui/sidebar';
|
||||||
import { AppWindow, Home, LogOut, Moon, Sun, Users } from 'lucide-react';
|
import { AppWindow, ChartLine, FileLock2, Home, LogOut, LucideIcon, Moon, Sun, Users } from 'lucide-react';
|
||||||
import React from 'react';
|
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
|
@ -21,50 +20,126 @@ import {
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { LogoutLink } from '@/ory';
|
import { LogoutLink } from '@/ory';
|
||||||
|
import React from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
|
|
||||||
|
interface SidebarGroup {
|
||||||
|
type: 'group';
|
||||||
|
label: string;
|
||||||
|
items: SidebarItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SidebarItem {
|
||||||
|
type: 'item';
|
||||||
|
label: string;
|
||||||
|
path: string;
|
||||||
|
icon: LucideIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SidebarContent = SidebarItem | SidebarGroup
|
||||||
|
|
||||||
|
function renderSidebarMenuItem(item: SidebarItem, key: number, collapsed: boolean) {
|
||||||
|
return (
|
||||||
|
<Tooltip key={key} delayDuration={500}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<SidebarMenuItem>
|
||||||
|
<SidebarMenuButton asChild>
|
||||||
|
<Link href={item.path}>
|
||||||
|
<item.icon/>
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</Link>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="right" className={collapsed ? '' : 'hidden'}>
|
||||||
|
{item.label}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||||
|
|
||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
|
|
||||||
const items = [
|
const { state } = useSidebar();
|
||||||
|
|
||||||
|
const items: SidebarContent[] = [
|
||||||
{
|
{
|
||||||
title: 'Home',
|
label: 'Application',
|
||||||
url: '/',
|
type: 'group',
|
||||||
icon: Home,
|
items: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
label: 'Home',
|
||||||
|
path: '/',
|
||||||
|
icon: Home,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
label: 'Analytics',
|
||||||
|
path: '/analytics',
|
||||||
|
icon: ChartLine,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Users',
|
label: 'Ory Kratos',
|
||||||
url: '/user',
|
type: 'group',
|
||||||
icon: Users,
|
items: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
label: 'Users',
|
||||||
|
path: '/user',
|
||||||
|
icon: Users,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Applications',
|
label: 'Ory Hydra',
|
||||||
url: '/application',
|
type: 'group',
|
||||||
icon: AppWindow,
|
items: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
label: 'Clients',
|
||||||
|
path: '/client',
|
||||||
|
icon: AppWindow,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Ory Keto',
|
||||||
|
type: 'group',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
label: 'Relations',
|
||||||
|
path: '/relation',
|
||||||
|
icon: FileLock2,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sidebar variant="inset" collapsible="icon" {...props}>
|
<Sidebar variant="inset" collapsible="icon" {...props}>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<SidebarGroup>
|
<SidebarMenu>
|
||||||
<SidebarGroupLabel>Application</SidebarGroupLabel>
|
{items.map((item, index) => {
|
||||||
<SidebarGroupContent>
|
switch (item.type) {
|
||||||
<SidebarMenu>
|
case 'item':
|
||||||
{items.map((item) => (
|
return renderSidebarMenuItem(item, index, state === 'collapsed');
|
||||||
<SidebarMenuItem key={item.title}>
|
case 'group':
|
||||||
<SidebarMenuButton asChild>
|
return (
|
||||||
<Link href={item.url}>
|
<SidebarGroup key={index}>
|
||||||
<item.icon/>
|
<SidebarGroupLabel>{item.label}</SidebarGroupLabel>
|
||||||
<span>{item.title}</span>
|
{item.items.map((subItem, subIndex) => renderSidebarMenuItem(subItem, subIndex, state === 'collapsed'))}
|
||||||
</Link>
|
</SidebarGroup>
|
||||||
</SidebarMenuButton>
|
);
|
||||||
</SidebarMenuItem>
|
}
|
||||||
))}
|
})}
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarGroupContent>
|
|
||||||
</SidebarGroup>
|
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarFooter>
|
<SidebarFooter>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
|
|
Loading…
Add table
Reference in a new issue