| import React from 'react'; |
| import { Plus, MessageSquare, Menu, ChevronLeft } from 'lucide-react'; |
|
|
| interface SidebarProps { |
| isOpen: boolean; |
| setIsOpen: (isOpen: boolean) => void; |
| onNewChat: () => void; |
| sessions: Array<{ id: string; preview: string; timestamp: number }>; |
| currentSessionId: string | null; |
| onSelectSession: (id: string) => void; |
| } |
|
|
| export const Sidebar: React.FC<SidebarProps> = ({ |
| isOpen, |
| setIsOpen, |
| onNewChat, |
| sessions, |
| currentSessionId, |
| onSelectSession |
| }) => { |
| return ( |
| <> |
| {/* Mobile Overlay */} |
| {isOpen && ( |
| <div |
| className="fixed inset-0 bg-black/50 z-40 md:hidden" |
| onClick={() => setIsOpen(false)} |
| /> |
| )} |
| |
| {/* Sidebar Container */} |
| <div className={` |
| fixed md:static inset-y-0 left-0 z-50 |
| h-screen bg-background/95 backdrop-blur-xl |
| transition-all duration-300 ease-in-out |
| flex flex-col border-r border-white/5 shadow-[4px_0_24px_rgba(0,0,0,0.2)] |
| ${isOpen ? 'w-[280px] translate-x-0' : 'w-0 -translate-x-full md:w-[68px] md:translate-x-0'} |
| `}> |
| |
| {/* Header (Hamburger Menu) */} |
| <div className="p-3 flex items-center h-[60px]"> |
| <button |
| onClick={() => setIsOpen(!isOpen)} |
| className="p-2.5 hover:bg-white/5 rounded-full transition-transform active:scale-95 text-slate-400 hover:text-slate-200" |
| > |
| <Menu size={20} /> |
| </button> |
| {isOpen && ( |
| <div className="flex-1 flex justify-end md:hidden"> |
| <button |
| onClick={() => setIsOpen(false)} |
| className="p-2.5 hover:bg-white/5 rounded-full transition-transform active:scale-95 text-slate-400" |
| > |
| <ChevronLeft size={20} /> |
| </button> |
| </div> |
| )} |
| </div> |
| |
| {/* New Chat Button */} |
| <div className="px-3 mt-4"> |
| <button |
| onClick={onNewChat} |
| className={` |
| flex items-center gap-3 bg-white/5 hover:bg-white/10 |
| text-slate-200 font-medium transition-all active:scale-95 |
| ${isOpen ? 'w-full py-3 px-4 rounded-2xl' : 'w-11 h-11 justify-center rounded-full ml-1'} |
| `} |
| > |
| <Plus size={isOpen ? 18 : 20} className="shrink-0 text-blue-400" /> |
| {isOpen && <span>New Chat</span>} |
| </button> |
| </div> |
| |
| {/* Recent Chats Section */} |
| <div className="flex-1 overflow-y-auto mt-6 px-3 custom-scrollbar"> |
| {isOpen && ( |
| <div> |
| <p className="text-xs font-semibold text-gray-400 mb-2 px-2 uppercase tracking-wider"> |
| Recent |
| </p> |
| <div className="flex flex-col gap-1"> |
| {sessions.length === 0 ? ( |
| <p className="text-sm text-zinc-500 px-2 mt-2">No previous chats</p> |
| ) : ( |
| sessions.map(session => ( |
| <button |
| key={session.id} |
| onClick={() => onSelectSession(session.id)} |
| className={` |
| flex items-center gap-3 w-full p-2.5 rounded-xl text-left transition-all active:scale-95 |
| ${currentSessionId === session.id |
| ? 'bg-primary/20 text-white font-medium shadow-[0_0_10px_rgba(139,92,246,0.1)]' |
| : 'hover:bg-white/5 text-gray-300 hover:text-white'} |
| `} |
| > |
| <MessageSquare size={16} className="shrink-0 opacity-70" /> |
| <span className="text-sm truncate pr-2"> |
| {session.preview || "New Conversation"} |
| </span> |
| </button> |
| )) |
| )} |
| </div> |
| </div> |
| )} |
| </div> |
| </div> |
| </> |
| ); |
| }; |
|
|