feat: refactor AppSidebar to support nested tool menus with collapsible items
- Enhanced the AppSidebar component to recursively render tools with potential submenus. - Introduced a buildFullPath function for dynamic routing based on tool hierarchy. - Utilized the Collapsible component for better organization of tools with children. - Maintained existing footer and header structure for consistency.
This commit is contained in:
		| @@ -1,32 +1,89 @@ | |||||||
| import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenuButton, SidebarMenuItem } from "@/components/ui/sidebar"; | import type { ReactNode } from "react"; | ||||||
| import { tools } from "@/components/tool"; | import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenuButton, SidebarMenuItem, SidebarMenu, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton } from "@/components/ui/sidebar"; | ||||||
|  | import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@/components/ui/collapsible"; | ||||||
|  | import { tools, type Tool } from "@/components/tool"; | ||||||
| import { Link } from "react-router-dom"; | import { Link } from "react-router-dom"; | ||||||
| import { ModeToggle } from "@/components/theme/toggle"; | import { ModeToggle } from "@/components/theme/toggle"; | ||||||
| import { Button } from "../ui/button"; | import { Button } from "../ui/button"; | ||||||
|  | import { ChevronRight } from "lucide-react"; | ||||||
|  |  | ||||||
| export const AppSidebar = () => ( | export const AppSidebar = () => { | ||||||
|  |   // 递归构建完整路径 | ||||||
|  |   const buildFullPath = (pathSegments: string[]): string => { | ||||||
|  |     return `/tool/${pathSegments.join("/")}`; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 递归渲染菜单项 | ||||||
|  |   const renderMenuItem = (tool: Tool, parentPaths: string[] = []): ReactNode => { | ||||||
|  |     const currentPaths = [...parentPaths, tool.path]; | ||||||
|  |  | ||||||
|  |     if (tool.children) { | ||||||
|  |       // 有子菜单的项目 | ||||||
|  |       return ( | ||||||
|  |         <Collapsible | ||||||
|  |           key={tool.name} | ||||||
|  |           defaultOpen={false} | ||||||
|  |           className="group/collapsible" | ||||||
|  |         > | ||||||
|  |           <SidebarMenuItem> | ||||||
|  |             <CollapsibleTrigger asChild> | ||||||
|  |               <SidebarMenuButton tooltip={tool.description}> | ||||||
|  |                 {tool.icon} | ||||||
|  |                 <span>{tool.name}</span> | ||||||
|  |                 <ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" /> | ||||||
|  |               </SidebarMenuButton> | ||||||
|  |             </CollapsibleTrigger> | ||||||
|  |             <CollapsibleContent> | ||||||
|  |               <SidebarMenuSub> | ||||||
|  |                 {tool.children.map((child) => ( | ||||||
|  |                   <SidebarMenuSubItem key={child.name}> | ||||||
|  |                     {child.children ? ( | ||||||
|  |                       renderMenuItem(child, currentPaths) | ||||||
|  |                     ) : ( | ||||||
|  |                       <SidebarMenuSubButton asChild> | ||||||
|  |                         <Link | ||||||
|  |                           to={buildFullPath([...currentPaths, child.path])} | ||||||
|  |                           title={child.description} | ||||||
|  |                         > | ||||||
|  |                           {child.icon} | ||||||
|  |                           <span>{child.name}</span> | ||||||
|  |                         </Link> | ||||||
|  |                       </SidebarMenuSubButton> | ||||||
|  |                     )} | ||||||
|  |                   </SidebarMenuSubItem> | ||||||
|  |                 ))} | ||||||
|  |               </SidebarMenuSub> | ||||||
|  |             </CollapsibleContent> | ||||||
|  |           </SidebarMenuItem> | ||||||
|  |         </Collapsible> | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 没有子菜单的项目 | ||||||
|  |     return ( | ||||||
|  |       <SidebarMenuItem key={tool.name}> | ||||||
|  |         <SidebarMenuButton asChild tooltip={tool.description}> | ||||||
|  |           <Link to={buildFullPath(currentPaths)}> | ||||||
|  |             {tool.icon} | ||||||
|  |             <span>{tool.name}</span> | ||||||
|  |           </Link> | ||||||
|  |         </SidebarMenuButton> | ||||||
|  |       </SidebarMenuItem> | ||||||
|  |     ); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|     <Sidebar> |     <Sidebar> | ||||||
|       <SidebarHeader className="text-2xl font-bold flex justify-center items-center"> |       <SidebarHeader className="text-2xl font-bold flex justify-center items-center"> | ||||||
|         Lite Kit |         Lite Kit | ||||||
|       </SidebarHeader> |       </SidebarHeader> | ||||||
|       <SidebarContent> |       <SidebarContent> | ||||||
|         <SidebarGroup> |         <SidebarGroup> | ||||||
|         <SidebarGroupLabel> |           <SidebarGroupLabel>Tools</SidebarGroupLabel> | ||||||
|           Tools |  | ||||||
|         </SidebarGroupLabel> |  | ||||||
|           <SidebarGroupContent> |           <SidebarGroupContent> | ||||||
|           { |             <SidebarMenu> | ||||||
|             tools.map((tool) => ( |               {tools.map((tool) => renderMenuItem(tool))} | ||||||
|               <SidebarMenuItem key={tool.name}> |             </SidebarMenu> | ||||||
|                 <SidebarMenuButton asChild> |  | ||||||
|                   <Link to={`/tool/${tool.path}`} title={tool.description}> |  | ||||||
|                     {tool.icon} |  | ||||||
|                     {tool.name} |  | ||||||
|                   </Link> |  | ||||||
|                 </SidebarMenuButton> |  | ||||||
|               </SidebarMenuItem> |  | ||||||
|             )) |  | ||||||
|           } |  | ||||||
|           </SidebarGroupContent> |           </SidebarGroupContent> | ||||||
|         </SidebarGroup> |         </SidebarGroup> | ||||||
|       </SidebarContent> |       </SidebarContent> | ||||||
| @@ -37,4 +94,5 @@ export const AppSidebar = () => ( | |||||||
|         <ModeToggle /> |         <ModeToggle /> | ||||||
|       </SidebarFooter> |       </SidebarFooter> | ||||||
|     </Sidebar> |     </Sidebar> | ||||||
| ) |   ); | ||||||
|  | }; | ||||||
		Reference in New Issue
	
	Block a user
	 typist
					typist