Jules
Final deployment with all fixes and verified content
c09f67c
import {
ChevronDown,
ChevronRight,
Clock,
FlaskConical,
Layers,
Moon,
PanelLeft,
PanelLeftClose,
Play,
Sun,
} from "lucide-react";
import * as React from "react";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
type NavItem = "runs" | "schedulers" | "queues" | "test";
interface SidebarProps {
queues: string[];
activeNav: NavItem;
activeQueue?: string;
onNavSelect: (nav: NavItem) => void;
onQueueSelect: (queue: string) => void;
isDark: boolean;
onToggleTheme: () => void;
title?: string;
collapsed: boolean;
onToggleCollapse: () => void;
}
export function Sidebar({
queues,
activeNav,
activeQueue,
onNavSelect,
onQueueSelect,
isDark,
onToggleTheme,
title = "Workbench",
collapsed,
onToggleCollapse,
}: SidebarProps) {
const [queuesExpanded, setQueuesExpanded] = React.useState(true);
const navItems: { id: NavItem; label: string; icon: typeof Play }[] = [
{ id: "runs", label: "Runs", icon: Play },
{ id: "schedulers", label: "Schedulers", icon: Clock },
{ id: "test", label: "Test", icon: FlaskConical },
];
return (
<>
{/* Header */}
<div className="h-14 border-b border-border flex items-center justify-between px-3">
{!collapsed && (
<h1 className="font-semibold text-sm truncate">{title}</h1>
)}
<Button
variant="ghost"
size="icon"
onClick={onToggleCollapse}
className={cn("h-8 w-8 shrink-0", collapsed && "mx-auto")}
>
{collapsed ? (
<PanelLeft className="h-4 w-4" />
) : (
<PanelLeftClose className="h-4 w-4" />
)}
</Button>
</div>
{/* Navigation */}
<ScrollArea className="flex-1">
<nav className={cn("p-2 space-y-1", collapsed && "px-1")}>
{/* Main nav items */}
{navItems.map((item) =>
collapsed ? (
<Tooltip key={item.id}>
<TooltipTrigger asChild>
<Button
variant={activeNav === item.id ? "secondary" : "ghost"}
size="icon"
className="w-full h-9"
onClick={() => onNavSelect(item.id)}
>
<item.icon className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="right">{item.label}</TooltipContent>
</Tooltip>
) : (
<Button
key={item.id}
variant={activeNav === item.id ? "secondary" : "ghost"}
className="w-full justify-start h-9"
onClick={() => onNavSelect(item.id)}
>
<item.icon className="mr-2 h-4 w-4" />
{item.label}
</Button>
),
)}
{/* Queues Section */}
<div className="pt-3">
{collapsed ? (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={activeNav === "queues" ? "secondary" : "ghost"}
size="icon"
className="w-full h-9"
onClick={() => onNavSelect("queues")}
>
<Layers className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="right">Queues</TooltipContent>
</Tooltip>
) : (
<>
<Button
variant="ghost"
className="w-full justify-between h-9 px-2"
onClick={() => setQueuesExpanded(!queuesExpanded)}
>
<span className="flex items-center">
<Layers className="mr-2 h-4 w-4" />
Queues
</span>
{queuesExpanded ? (
<ChevronDown className="h-3 w-3 text-muted-foreground" />
) : (
<ChevronRight className="h-3 w-3 text-muted-foreground" />
)}
</Button>
{queuesExpanded && (
<div className="pl-4 space-y-0.5 mt-1">
{queues.map((queue) => (
<Button
key={queue}
variant={activeQueue === queue ? "secondary" : "ghost"}
className="w-full justify-start font-mono text-xs h-8"
onClick={() => onQueueSelect(queue)}
>
<span className="truncate">{queue}</span>
</Button>
))}
</div>
)}
</>
)}
</div>
</nav>
</ScrollArea>
{/* Footer */}
<div className="border-t border-border p-2">
{collapsed ? (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
onClick={onToggleTheme}
className="w-full h-9"
>
{isDark ? (
<Sun className="h-4 w-4" />
) : (
<Moon className="h-4 w-4" />
)}
</Button>
</TooltipTrigger>
<TooltipContent side="right">
{isDark ? "Light mode" : "Dark mode"}
</TooltipContent>
</Tooltip>
) : (
<Button
variant="ghost"
size="icon"
onClick={onToggleTheme}
className="w-full h-9"
>
{isDark ? (
<Sun className="h-4 w-4" />
) : (
<Moon className="h-4 w-4" />
)}
</Button>
)}
</div>
</>
);
}