import * as React from 'react'; import { ChevronLeft, ChevronRight, X } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Button } from './button'; import { Card } from './card'; export interface SidebarProps { /** * Content to display in the sidebar */ children: React.ReactNode; /** * Position of the sidebar * @default 'left' */ position?: 'left' | 'right'; /** * Width of the sidebar when open * @default 'w-64' */ width?: string; /** * Whether the sidebar is open * @default true */ open?: boolean; /** * Callback when open state changes */ onOpenChange?: (open: boolean) => void; /** * Whether the sidebar is collapsible * @default true */ collapsible?: boolean; /** * Title/header for the sidebar */ title?: React.ReactNode; /** * Optional icon to display next to the title */ icon?: React.ReactNode; /** * Additional CSS classes for the container */ className?: string; /** * Additional CSS classes for the sidebar content */ contentClassName?: string; /** * Whether to show a backdrop on mobile when open * @default true */ showBackdrop?: boolean; } /** * Sidebar - Reusable sidebar component for filters and content * * A generic sidebar component that can be used to display filters, * additional content, or any sidebar-worthy information. Supports * collapsible functionality and positioning. * * @example * ```tsx * *
Filter content here
*
* ``` * * @example * ```tsx * } * position="right" * open={isOpen} * onOpenChange={setIsOpen} * width="w-80" * > * * * ``` */ export function Sidebar({ children, position = 'left', width = 'w-64', open: controlledOpen, onOpenChange, collapsible = true, title, icon, className, contentClassName, showBackdrop = true, }: SidebarProps) { const [uncontrolledOpen, setUncontrolledOpen] = React.useState(true); // Use controlled state if provided, otherwise use uncontrolled const isOpen = controlledOpen !== undefined ? controlledOpen : uncontrolledOpen; const handleToggle = () => { const newOpen = !isOpen; if (controlledOpen === undefined) { setUncontrolledOpen(newOpen); } onOpenChange?.(newOpen); }; const ChevronIcon = position === 'left' ? ChevronLeft : ChevronRight; const isCollapsed = collapsible && !isOpen; return ( <> {/* Mobile Backdrop */} {showBackdrop && isOpen && (