Skip to content

Commit 9e0241c

Browse files
committed
feat: 💄 Sub Appsidebar Menu
- Implement submenu component with shadcn-vue styling - Integrate submenu into existing navigation structure
1 parent 5ae6361 commit 9e0241c

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

resources/js/components/AppSidebar.vue

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@ const mainNavItems: NavItem[] = [
1414
href: '/dashboard',
1515
icon: LayoutGrid,
1616
},
17+
// Example
18+
// {
19+
// title: 'User Management',
20+
// href: '#',
21+
// icon: Shield,
22+
// children: [
23+
// {
24+
// title: 'Roles',
25+
// href: '#',
26+
// },
27+
// {
28+
// title: 'Permissions',
29+
// href: '#',
30+
// },
31+
// {
32+
// title: 'Users',
33+
// href: '#',
34+
// },
35+
// ],
36+
// },
1737
];
1838
1939
const footerNavItems: NavItem[] = [
@@ -37,7 +57,7 @@ const footerNavItems: NavItem[] = [
3757
<SidebarMenuItem>
3858
<SidebarMenuButton size="lg" as-child>
3959
<Link :href="route('dashboard')">
40-
<AppLogo />
60+
<AppLogo />
4161
</Link>
4262
</SidebarMenuButton>
4363
</SidebarMenuItem>
Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,64 @@
11
<script setup lang="ts">
2-
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
2+
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem } from '@/components/ui/sidebar'
33
import { type NavItem, type SharedData } from '@/types';
44
import { Link, usePage } from '@inertiajs/vue3';
5+
import { ChevronRight } from 'lucide-vue-next'
6+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'
57
68
defineProps<{
79
items: NavItem[];
810
}>();
911
1012
const page = usePage<SharedData>();
13+
14+
function isChildActive(item: { children: any[], href: string }) {
15+
return item.children?.some(child => child.href === page.url) || item.href === page.url
16+
}
1117
</script>
1218

1319
<template>
1420
<SidebarGroup class="px-2 py-0">
1521
<SidebarGroupLabel>Platform</SidebarGroupLabel>
1622
<SidebarMenu>
17-
<SidebarMenuItem v-for="item in items" :key="item.title">
18-
<SidebarMenuButton
19-
as-child :is-active="item.href === page.url"
20-
:tooltip="item.title"
21-
>
22-
<Link :href="item.href">
23+
<template v-for="item in items" :key="item.title">
24+
<!-- Regular items (no children) -->
25+
<SidebarMenuItem v-if="!item.children">
26+
<SidebarMenuButton as-child :is-active="item.href === page.url" :tooltip="item.title">
27+
<Link :href="item.href">
2328
<component :is="item.icon" />
2429
<span>{{ item.title }}</span>
25-
</Link>
26-
</SidebarMenuButton>
27-
</SidebarMenuItem>
30+
</Link>
31+
</SidebarMenuButton>
32+
</SidebarMenuItem>
33+
34+
<!-- Collapsible items (with children) -->
35+
<Collapsible v-else :default-open="isChildActive({ children: item.children || [], href: item.href })"
36+
class="group/collapsible">
37+
<SidebarMenuItem>
38+
<CollapsibleTrigger as-child>
39+
<SidebarMenuButton
40+
:is-active="isChildActive({ children: item.children || [], href: item.href })"
41+
:tooltip="item.title">
42+
<component :is="item.icon" v-if="item.icon" />
43+
<span>{{ item.title }}</span>
44+
<ChevronRight
45+
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
46+
</SidebarMenuButton>
47+
</CollapsibleTrigger>
48+
<CollapsibleContent>
49+
<SidebarMenuSub>
50+
<SidebarMenuSubItem v-for="subItem in item.children" :key="subItem.title">
51+
<SidebarMenuSubButton as-child :is-active="subItem.href === page.url">
52+
<Link :href="subItem.href">
53+
<span>{{ subItem.title }}</span>
54+
</Link>
55+
</SidebarMenuSubButton>
56+
</SidebarMenuSubItem>
57+
</SidebarMenuSub>
58+
</CollapsibleContent>
59+
</SidebarMenuItem>
60+
</Collapsible>
61+
</template>
2862
</SidebarMenu>
2963
</SidebarGroup>
3064
</template>

resources/js/types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface NavItem {
1616
href: string;
1717
icon?: LucideIcon;
1818
isActive?: boolean;
19+
children?: Array;
1920
}
2021

2122
export interface SharedData extends PageProps {

0 commit comments

Comments
 (0)