Active menu item follow react router state
Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
|||||||
} from "@/components/ui/sidebar";
|
} from "@/components/ui/sidebar";
|
||||||
import type { AppSidebarQuery as AppSidebarQueryType } from "./__generated__/AppSidebarQuery.graphql";
|
import type { AppSidebarQuery as AppSidebarQueryType } from "./__generated__/AppSidebarQuery.graphql";
|
||||||
import { TeamSwitcher } from "@/components/TeamSwitcher";
|
import { TeamSwitcher } from "@/components/TeamSwitcher";
|
||||||
|
import { url } from "inspector";
|
||||||
const staticData = {
|
const staticData = {
|
||||||
user: {
|
user: {
|
||||||
name: "shadcn",
|
name: "shadcn",
|
||||||
@@ -46,7 +47,7 @@ const staticData = {
|
|||||||
{
|
{
|
||||||
title: "Organizations",
|
title: "Organizations",
|
||||||
icon: Building,
|
icon: Building,
|
||||||
isActive: true,
|
url: "/peoples",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
title: "Peoples",
|
title: "Peoples",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ChevronRight, type LucideIcon } from "lucide-react";
|
import { ChevronRight, type LucideIcon } from "lucide-react";
|
||||||
import { Link } from "react-router";
|
import { Link, useLocation } from "react-router";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Collapsible,
|
Collapsible,
|
||||||
@@ -34,45 +34,87 @@ export function NavMain({
|
|||||||
}[];
|
}[];
|
||||||
}[];
|
}[];
|
||||||
}) {
|
}) {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
// Determine if an item is active based on the current route
|
||||||
|
const isItemActive = (item: { url?: string; items?: { url: string }[] }) => {
|
||||||
|
// If the item has a URL and it matches the current path
|
||||||
|
if (item.url && location.pathname.startsWith(item.url)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the item has sub-items, check if any of them match the current path
|
||||||
|
if (item.items?.length) {
|
||||||
|
return item.items.some((subItem) =>
|
||||||
|
location.pathname.startsWith(subItem.url)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>Compliance</SidebarGroupLabel>
|
<SidebarGroupLabel>Compliance</SidebarGroupLabel>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
{items.map((item) => (
|
{items.map((item) => {
|
||||||
<Collapsible key={item.title} asChild defaultOpen={item.isActive}>
|
const active = isItemActive(item) || item.isActive;
|
||||||
<SidebarMenuItem>
|
|
||||||
<SidebarMenuButton asChild tooltip={item.title}>
|
return (
|
||||||
<Link to={item.url ?? "#"}>
|
<Collapsible key={item.title} asChild defaultOpen={active}>
|
||||||
<item.icon />
|
<SidebarMenuItem>
|
||||||
<span>{item.title}</span>
|
<SidebarMenuButton
|
||||||
</Link>
|
asChild
|
||||||
</SidebarMenuButton>
|
tooltip={item.title}
|
||||||
{item.items?.length ? (
|
data-active={active ? "true" : undefined}
|
||||||
<>
|
className={active ? "text-primary font-medium" : ""}
|
||||||
<CollapsibleTrigger asChild>
|
>
|
||||||
<SidebarMenuAction className="data-[state=open]:rotate-90">
|
<Link to={item.url ?? "#"}>
|
||||||
<ChevronRight />
|
<item.icon />
|
||||||
<span className="sr-only">Toggle</span>
|
<span>{item.title}</span>
|
||||||
</SidebarMenuAction>
|
</Link>
|
||||||
</CollapsibleTrigger>
|
</SidebarMenuButton>
|
||||||
<CollapsibleContent>
|
{item.items?.length ? (
|
||||||
<SidebarMenuSub>
|
<>
|
||||||
{item.items?.map((subItem) => (
|
<CollapsibleTrigger asChild>
|
||||||
<SidebarMenuSubItem key={subItem.title}>
|
<SidebarMenuAction className="data-[state=open]:rotate-90">
|
||||||
<SidebarMenuSubButton asChild>
|
<ChevronRight />
|
||||||
<Link to={subItem.url}>
|
<span className="sr-only">Toggle</span>
|
||||||
<span>{subItem.title}</span>
|
</SidebarMenuAction>
|
||||||
</Link>
|
</CollapsibleTrigger>
|
||||||
</SidebarMenuSubButton>
|
<CollapsibleContent>
|
||||||
</SidebarMenuSubItem>
|
<SidebarMenuSub>
|
||||||
))}
|
{item.items?.map((subItem) => {
|
||||||
</SidebarMenuSub>
|
const subItemActive = location.pathname.startsWith(
|
||||||
</CollapsibleContent>
|
subItem.url
|
||||||
</>
|
);
|
||||||
) : null}
|
|
||||||
</SidebarMenuItem>
|
return (
|
||||||
</Collapsible>
|
<SidebarMenuSubItem key={subItem.title}>
|
||||||
))}
|
<SidebarMenuSubButton
|
||||||
|
asChild
|
||||||
|
data-active={subItemActive ? "true" : undefined}
|
||||||
|
className={
|
||||||
|
subItemActive
|
||||||
|
? "text-primary font-medium"
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Link to={subItem.url}>
|
||||||
|
<span>{subItem.title}</span>
|
||||||
|
</Link>
|
||||||
|
</SidebarMenuSubButton>
|
||||||
|
</SidebarMenuSubItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SidebarMenuSub>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
</SidebarMenuItem>
|
||||||
|
</Collapsible>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</SidebarMenu>
|
</SidebarMenu>
|
||||||
</SidebarGroup>
|
</SidebarGroup>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user