diff --git a/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx b/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx index 43edfed8951d..49c9adea373b 100644 --- a/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx +++ b/ui/desktop/src/components/GooseSidebar/AppSidebar.tsx @@ -13,6 +13,7 @@ import { } from '../ui/sidebar'; import { ChatSmart, Gear } from '../icons'; import { ViewOptions, View } from '../../App'; +import { useChatContext } from '../../contexts/ChatContext'; interface SidebarProps { onSelectSession: (sessionId: string) => void; @@ -23,12 +24,80 @@ interface SidebarProps { currentPath?: string; } -// Main Sidebar Component +interface NavigationItem { + type: 'item'; + path: string; + label: string; + icon: React.ComponentType<{ className?: string }>; + tooltip: string; +} + +interface NavigationSeparator { + type: 'separator'; +} + +type NavigationEntry = NavigationItem | NavigationSeparator; + +const menuItems: NavigationEntry[] = [ + { + type: 'item', + path: '/', + label: 'Home', + icon: Home, + tooltip: 'Go back to the main chat screen', + }, + { type: 'separator' }, + { + type: 'item', + path: '/pair', + label: 'Chat', + icon: ChatSmart, + tooltip: 'Start pairing with Goose', + }, + { + type: 'item', + path: '/sessions', + label: 'History', + icon: History, + tooltip: 'View your session history', + }, + { type: 'separator' }, + { + type: 'item', + path: '/recipes', + label: 'Recipes', + icon: FileText, + tooltip: 'Browse your saved recipes', + }, + { + type: 'item', + path: '/schedules', + label: 'Scheduler', + icon: Clock, + tooltip: 'Manage scheduled runs', + }, + { + type: 'item', + path: '/extensions', + label: 'Extensions', + icon: Puzzle, + tooltip: 'Manage your extensions', + }, + { type: 'separator' }, + { + type: 'item', + path: '/settings', + label: 'Settings', + icon: Gear, + tooltip: 'Configure Goose settings', + }, +]; + const AppSidebar: React.FC = ({ currentPath }) => { const navigate = useNavigate(); + const chatContext = useChatContext(); useEffect(() => { - // Trigger animation after a small delay const timer = setTimeout(() => { // setIsVisible(true); }, 100); @@ -36,156 +105,62 @@ const AppSidebar: React.FC = ({ currentPath }) => { return () => clearTimeout(timer); }, []); - // Helper function to check if a path is active + useEffect(() => { + const currentItem = menuItems.find( + (item) => item.type === 'item' && item.path === currentPath + ) as NavigationItem | undefined; + + const titleBits = ['Goose']; + + if ( + currentPath === '/pair' && + chatContext?.chat?.title && + chatContext.chat.title !== 'New Chat' + ) { + titleBits.push(chatContext.chat.title); + } else if (currentPath !== '/' && currentItem) { + titleBits.push(currentItem.label); + } + + document.title = titleBits.join(' - '); + }, [currentPath, chatContext?.chat?.title]); + const isActivePath = (path: string) => { return currentPath === path; }; + const renderMenuItem = (entry: NavigationEntry, index: number) => { + if (entry.type === 'separator') { + return ; + } + + const IconComponent = entry.icon; + + return ( + + +
+ + navigate(entry.path)} + isActive={isActivePath(entry.path)} + tooltip={entry.tooltip} + className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" + > + + {entry.label} + + +
+
+
+ ); + }; + return ( <> - {/* Menu */} - - {/* Navigation Group */} - - -
- - { - navigate('/'); - }} - isActive={isActivePath('/')} - tooltip="Go back to the main chat screen" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Home - - -
-
-
- - - - {/* Chat & Configuration Group */} - - -
- - navigate('/pair')} - isActive={isActivePath('/pair')} - tooltip="Start pairing with Goose" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Chat - - -
- -
- - navigate('/sessions')} - isActive={isActivePath('/sessions')} - tooltip="View your session history" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - History - - -
-
-
- - - - {/* Content Group */} - - - {/*
*/} - {/* */} - {/* navigate('/projects')}*/} - {/* isActive={isActivePath('/projects')}*/} - {/* tooltip="Manage your projects"*/} - {/* className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium"*/} - {/* >*/} - {/* */} - {/* Projects*/} - {/* */} - {/* */} - {/*
*/} - -
- - navigate('/recipes')} - isActive={isActivePath('/recipes')} - tooltip="Browse your saved recipes" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Recipes - - -
- -
- - navigate('/schedules')} - isActive={isActivePath('/schedules')} - tooltip="Manage scheduled runs" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Scheduler - - -
- -
- - navigate('/extensions')} - isActive={isActivePath('/extensions')} - tooltip="Manage your extensions" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Extensions - - -
-
-
- - - - {/* Settings Group */} - - -
- - navigate('/settings')} - isActive={isActivePath('/settings')} - tooltip="Configure Goose settings" - className="w-full justify-start px-3 rounded-lg h-fit hover:bg-background-medium/50 transition-all duration-200 data-[active=true]:bg-background-medium" - > - - Settings - - -
-
-
-
+ {menuItems.map((entry, index) => renderMenuItem(entry, index))}