86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import Link from "next/link";
|
|
import type { LucideIcon } from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
|
|
import { AppCard } from "@/components/ui/app-card";
|
|
import { CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type SidebarItem = {
|
|
label: string;
|
|
href: string;
|
|
icon: LucideIcon;
|
|
active?: boolean;
|
|
children?: SidebarItem[];
|
|
};
|
|
|
|
type AppSidebarProps = {
|
|
title: string;
|
|
description: string;
|
|
items: SidebarItem[];
|
|
footer?: ReactNode;
|
|
};
|
|
|
|
export function AppSidebar({
|
|
title,
|
|
description,
|
|
items,
|
|
footer,
|
|
}: AppSidebarProps) {
|
|
return (
|
|
<AppCard className="sticky top-6 overflow-hidden bg-sidebar text-sidebar-foreground shadow-sidebar">
|
|
<CardHeader className="pb-4">
|
|
<CardTitle className="text-base font-semibold">{title}</CardTitle>
|
|
<p className="text-sm text-sidebar-foreground/72">{description}</p>
|
|
</CardHeader>
|
|
<CardContent className="space-y-1 px-3 pb-3 pt-0">
|
|
{items.map((item) => {
|
|
const Icon = item.icon;
|
|
|
|
return (
|
|
<div key={item.label} className="space-y-1">
|
|
<Link
|
|
href={item.href}
|
|
className={cn(
|
|
"flex items-center gap-2 rounded-nested px-3 py-2 text-sm transition-colors",
|
|
item.active
|
|
? "bg-sidebar-primary text-sidebar-primary-foreground"
|
|
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
)}
|
|
>
|
|
<Icon className="h-4 w-4" />
|
|
<span>{item.label}</span>
|
|
</Link>
|
|
|
|
{item.children?.length ? (
|
|
<div className="ml-3 space-y-1 border-l border-sidebar-border pl-3">
|
|
{item.children.map((child) => {
|
|
const ChildIcon = child.icon;
|
|
|
|
return (
|
|
<Link
|
|
key={child.label}
|
|
href={child.href}
|
|
className={cn(
|
|
"flex items-center gap-2 rounded-nested px-3 py-2 text-sm transition-colors",
|
|
child.active
|
|
? "bg-sidebar-primary text-sidebar-primary-foreground"
|
|
: "text-sidebar-foreground/72 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
)}
|
|
>
|
|
<ChildIcon className="h-4 w-4" />
|
|
<span>{child.label}</span>
|
|
</Link>
|
|
);
|
|
})}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
})}
|
|
</CardContent>
|
|
{footer ? <div className="border-t border-sidebar-border px-4 py-3">{footer}</div> : null}
|
|
</AppCard>
|
|
);
|
|
}
|