feat: enhance sidebar component with recursive submenu rendering

- Implemented recursive rendering of submenu items in the sidebar for better navigation.
- Added support for collapsible submenus, improving user experience with nested tools.
- Refactored menu item rendering logic to utilize a new renderSubMenuContent function for cleaner code.
This commit is contained in:
typist
2025-10-29 08:33:22 +08:00
parent d553c3e04c
commit e98a344b95

View File

@@ -13,6 +13,46 @@ export const AppSidebar = () => {
return `/tool/${pathSegments.join("/")}`; return `/tool/${pathSegments.join("/")}`;
}; };
// 递归渲染子菜单内容
const renderSubMenuContent = (child: Tool, currentPaths: string[]): ReactNode => {
if (child.children) {
// 子菜单内的可折叠项
return (
<Collapsible defaultOpen={false} className="group/collapsible">
<CollapsibleTrigger asChild>
<SidebarMenuSubButton>
{child.icon}
<span>{child.name}</span>
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuSubButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{child.children.map((subChild) => (
<SidebarMenuSubItem key={subChild.name}>
{renderSubMenuContent(subChild, [...currentPaths, child.path])}
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</Collapsible>
);
}
// 叶子节点
return (
<SidebarMenuSubButton asChild>
<Link
to={buildFullPath([...currentPaths, child.path])}
title={child.description}
>
{child.icon}
<span>{child.name}</span>
</Link>
</SidebarMenuSubButton>
);
};
// 递归渲染菜单项 // 递归渲染菜单项
const renderMenuItem = (tool: Tool, parentPaths: string[] = []): ReactNode => { const renderMenuItem = (tool: Tool, parentPaths: string[] = []): ReactNode => {
const currentPaths = [...parentPaths, tool.path]; const currentPaths = [...parentPaths, tool.path];
@@ -20,12 +60,11 @@ export const AppSidebar = () => {
if (tool.children) { if (tool.children) {
// 有子菜单的项目 // 有子菜单的项目
return ( return (
<Collapsible <SidebarMenuItem key={tool.name}>
key={tool.name} <Collapsible
defaultOpen={false} defaultOpen={false}
className="group/collapsible" className="group/collapsible"
> >
<SidebarMenuItem>
<CollapsibleTrigger asChild> <CollapsibleTrigger asChild>
<SidebarMenuButton tooltip={tool.description}> <SidebarMenuButton tooltip={tool.description}>
{tool.icon} {tool.icon}
@@ -37,25 +76,13 @@ export const AppSidebar = () => {
<SidebarMenuSub> <SidebarMenuSub>
{tool.children.map((child) => ( {tool.children.map((child) => (
<SidebarMenuSubItem key={child.name}> <SidebarMenuSubItem key={child.name}>
{child.children ? ( {renderSubMenuContent(child, currentPaths)}
renderMenuItem(child, currentPaths)
) : (
<SidebarMenuSubButton asChild>
<Link
to={buildFullPath([...currentPaths, child.path])}
title={child.description}
>
{child.icon}
<span>{child.name}</span>
</Link>
</SidebarMenuSubButton>
)}
</SidebarMenuSubItem> </SidebarMenuSubItem>
))} ))}
</SidebarMenuSub> </SidebarMenuSub>
</CollapsibleContent> </CollapsibleContent>
</SidebarMenuItem> </Collapsible>
</Collapsible> </SidebarMenuItem>
); );
} }