Files
stack/apps/web/src/components/layout/sidebar.tsx
2026-03-13 13:33:45 +00:00

61 lines
1.8 KiB
TypeScript

'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { cn } from '@/lib/cn';
interface NavItem {
label: string;
href: string;
icon: string;
}
const navItems: NavItem[] = [
{ label: 'Chat', href: '/chat', icon: '💬' },
{ label: 'Tasks', href: '/tasks', icon: '📋' },
{ label: 'Projects', href: '/projects', icon: '📁' },
{ label: 'Settings', href: '/settings', icon: '⚙️' },
{ label: 'Admin', href: '/admin', icon: '🛡️' },
];
export function Sidebar(): React.ReactElement {
const pathname = usePathname();
return (
<aside className="fixed left-0 top-0 z-30 flex h-screen w-sidebar flex-col border-r border-surface-border bg-surface-card">
<div className="flex h-14 items-center px-4">
<Link href="/" className="text-lg font-semibold text-text-primary">
Mosaic
</Link>
</div>
<nav className="flex-1 space-y-1 px-2 py-2">
{navItems.map((item) => {
const isActive = pathname === item.href || pathname.startsWith(`${item.href}/`);
return (
<Link
key={item.href}
href={item.href}
className={cn(
'flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors',
isActive
? 'bg-blue-600/20 text-blue-400'
: 'text-text-secondary hover:bg-surface-elevated hover:text-text-primary',
)}
>
<span className="text-base" aria-hidden="true">
{item.icon}
</span>
{item.label}
</Link>
);
})}
</nav>
<div className="border-t border-surface-border p-4">
<p className="text-xs text-text-muted">Mosaic Stack v0.0.4</p>
</div>
</aside>
);
}