Files
smart-crop-ui/crop-x/src/components/app-sidebar.tsx

163 lines
4.2 KiB
TypeScript

import * as React from "react"
import { ChevronRight } from "lucide-react"
import Link from "next/link"
import { SearchForm } from "@/components/search-form"
import { VersionSwitcher } from "@/components/version-switcher"
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarRail,
} from "@/components/ui/sidebar"
import { useLayoutStore } from '@/stores/useLayoutStore';
// Define the interface for menu data
interface MenuItem {
title: string
url: string
isActive?: boolean
}
interface NavMainItem {
title: string
url: string
icon?: string
items: MenuItem[]
}
interface SidebarData {
navMain: NavMainItem[]
versions?: string[]
}
// Default data - used when no external data is provided
const defaultData: SidebarData = {
versions: ["1.0.0", "2.0.0"],
navMain: [
{
title: "Getting Started",
url: "#",
items: [
{
title: "Installation",
url: "#",
},
{
title: "Project Structure",
url: "#",
},
],
},
{
title: "Building Your Application",
url: "#",
items: [
{
title: "Routing",
url: "#",
},
{
title: "Data Fetching",
url: "#",
isActive: true,
},
{
title: "Rendering",
url: "#",
},
{
title: "Caching",
url: "#",
},
{
title: "Styling",
url: "#",
},
],
},
{
title: "API Reference",
url: "#",
items: [
{
title: "Components",
url: "#",
},
{
title: "File Conventions",
url: "#",
},
],
},
],
}
export interface AppSidebarProps extends React.ComponentProps<typeof Sidebar> {
data?: SidebarData
}
export function AppSidebar({ data, ...props }: AppSidebarProps) {
// Use external data if provided, otherwise use default data
const sidebarData = data || defaultData
const { navigatorHeight } = useLayoutStore();
return (
<Sidebar {...props} style = {{top: navigatorHeight + 'px'}}>
<SidebarContent className="gap-0" >
{/* We create a collapsible SidebarGroup for each parent. */}
{sidebarData.navMain.map((item) => (
<Collapsible
key={item.title}
title={item.title}
defaultOpen
className="group/collapsible"
>
<SidebarGroup>
<SidebarGroupLabel
asChild
className="group/label text-sm text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
>
<CollapsibleTrigger>
<div className="flex items-center">
{item.icon && <span className="mr-2">{item.icon}</span>}
{item.title}
<ChevronRight className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90" />
</div>
</CollapsibleTrigger>
</SidebarGroupLabel>
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
{item.items.map((subItem) => (
<SidebarMenuItem key={subItem.title}>
<SidebarMenuButton asChild isActive={subItem.isActive}>
{subItem.url.startsWith('#') ? (
<a href={subItem.url}>{subItem.title}</a>
) : (
<Link href={subItem.url}>{subItem.title}</Link>
)}
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</CollapsibleContent>
</SidebarGroup>
</Collapsible>
))}
</SidebarContent>
<SidebarRail />
</Sidebar>
)
}