import * as React from 'react'; import { cn } from '@slate-test-1770505673/ui'; import { ChevronRight, type LucideIcon } from 'lucide-react'; export interface NavItem { /** Display label */ label: string; /** URL to navigate to */ href: string; /** Icon component from lucide-react */ icon?: LucideIcon; /** Whether this item is currently active */ active?: boolean; /** Badge text to display */ badge?: string; /** Nested items for collapsible sections */ children?: NavItem[]; } export interface SidebarProps { /** Logo or brand element to display at the top */ logo?: React.ReactNode; /** Navigation items */ items: NavItem[]; /** Footer element (e.g., user menu, settings) */ footer?: React.ReactNode; /** Additional class names */ className?: string; /** Click handler for navigation items */ onNavigate?: (href: string) => void; } /** * Sidebar provides navigation for dashboard applications. * Supports icons, nested items, badges, and active state highlighting. * * @example * } * items={[ * { label: 'Dashboard', href: '/', icon: Home, active: true }, * { label: 'Users', href: '/users', icon: Users }, * { label: 'Settings', href: '/settings', icon: Settings }, * ]} * footer={} * /> */ export function Sidebar({ logo, items, footer, className, onNavigate, }: SidebarProps) { const [expanded, setExpanded] = React.useState>({}); const toggleExpanded = (label: string) => { setExpanded((prev) => ({ ...prev, [label]: !prev[label] })); }; const handleClick = (item: NavItem, e: React.MouseEvent) => { if (item.children) { e.preventDefault(); toggleExpanded(item.label); } else if (onNavigate) { e.preventDefault(); onNavigate(item.href); } }; return (
{/* Logo area */} {logo && (
{logo}
)} {/* Navigation */} {/* Footer */} {footer && (
{footer}
)}
); } interface NavItemComponentProps { item: NavItem; isExpanded?: boolean; depth?: number; onClick: (item: NavItem, e: React.MouseEvent) => void; onNavigate?: (href: string) => void; } function NavItemComponent({ item, isExpanded = false, depth = 0, onClick, onNavigate, }: NavItemComponentProps) { const Icon = item.icon; const hasChildren = item.children && item.children.length > 0; return (
  • onClick(item, e)} className={cn( 'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors', item.active ? 'bg-[var(--surface-200)] text-[var(--text-primary)]' : 'text-[var(--text-secondary)] hover:bg-[var(--surface-100)] hover:text-[var(--text-primary)]', depth > 0 && 'ml-6' )} > {Icon && } {item.label} {item.badge && ( {item.badge} )} {hasChildren && ( )} {/* Nested items */} {hasChildren && isExpanded && (
      {item.children!.map((child) => ( ))}
    )}
  • ); }