Add live ActiveAgentsPanel with real-time transcript feed, SidebarContext for responsive sidebar state, agent config form with reasoning effort, improved inbox with failed run alerts, enriched issue detail with project picker, and various component refinements across pages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import { useState } from "react";
|
|
import { ArrowUp, ArrowDown, Minus, AlertTriangle } from "lucide-react";
|
|
import { cn } from "../lib/utils";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
const priorityConfig: Record<string, { icon: typeof ArrowUp; color: string; label: string }> = {
|
|
critical: { icon: AlertTriangle, color: "text-red-400", label: "Critical" },
|
|
high: { icon: ArrowUp, color: "text-orange-400", label: "High" },
|
|
medium: { icon: Minus, color: "text-yellow-400", label: "Medium" },
|
|
low: { icon: ArrowDown, color: "text-blue-400", label: "Low" },
|
|
};
|
|
|
|
const allPriorities = ["critical", "high", "medium", "low"];
|
|
|
|
interface PriorityIconProps {
|
|
priority: string;
|
|
onChange?: (priority: string) => void;
|
|
className?: string;
|
|
showLabel?: boolean;
|
|
}
|
|
|
|
export function PriorityIcon({ priority, onChange, className, showLabel }: PriorityIconProps) {
|
|
const [open, setOpen] = useState(false);
|
|
const config = priorityConfig[priority] ?? priorityConfig.medium!;
|
|
const Icon = config.icon;
|
|
|
|
const icon = (
|
|
<span
|
|
className={cn(
|
|
"inline-flex items-center justify-center shrink-0",
|
|
config.color,
|
|
onChange && !showLabel && "cursor-pointer",
|
|
className
|
|
)}
|
|
>
|
|
<Icon className="h-3.5 w-3.5" />
|
|
</span>
|
|
);
|
|
|
|
if (!onChange) return showLabel ? <span className="inline-flex items-center gap-1.5">{icon}<span className="text-sm">{config.label}</span></span> : icon;
|
|
|
|
const trigger = showLabel ? (
|
|
<button className="inline-flex items-center gap-1.5 cursor-pointer hover:bg-accent/50 rounded px-1 -mx-1 py-0.5 transition-colors">
|
|
{icon}
|
|
<span className="text-sm">{config.label}</span>
|
|
</button>
|
|
) : icon;
|
|
|
|
return (
|
|
<Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
|
<PopoverContent className="w-36 p-1" align="start">
|
|
{allPriorities.map((p) => {
|
|
const c = priorityConfig[p]!;
|
|
const PIcon = c.icon;
|
|
return (
|
|
<Button
|
|
key={p}
|
|
variant="ghost"
|
|
size="sm"
|
|
className={cn("w-full justify-start gap-2 text-xs", p === priority && "bg-accent")}
|
|
onClick={() => {
|
|
onChange(p);
|
|
setOpen(false);
|
|
}}
|
|
>
|
|
<PIcon className={cn("h-3.5 w-3.5", c.color)} />
|
|
{c.label}
|
|
</Button>
|
|
);
|
|
})}
|
|
</PopoverContent>
|
|
</Popover>
|
|
);
|
|
}
|