mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
refactor(ui): migrate SectionHeader and ToolsSection to shadcn
This commit is contained in:
parent
eb23dc2e81
commit
bc9005c149
3 changed files with 74 additions and 107 deletions
|
|
@ -3848,11 +3848,6 @@
|
|||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/view_logs/LogDetailsDrawer/SectionHeader.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/view_logs/LogDetailsDrawer/SimpleMessageBlock.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
|
|
@ -3893,11 +3888,6 @@
|
|||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/view_logs/ToolsSection/ToolsSection.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/components/view_logs/VectorStoreViewer.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
|
|
@ -4028,4 +4018,4 @@
|
|||
"count": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
* SectionHeader - Datadog-style header with icon, label, metrics, and copy
|
||||
*/
|
||||
|
||||
import { Typography, Button, Tooltip } from "antd";
|
||||
import { MessageOutlined, CopyOutlined, DownOutlined, UpOutlined } from "@ant-design/icons";
|
||||
|
||||
const { Text } = Typography;
|
||||
import { ChevronDown, ChevronUp, Copy, MessageSquare } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/cva.config";
|
||||
|
||||
interface SectionHeaderProps {
|
||||
type: "input" | "output";
|
||||
|
|
@ -29,80 +29,57 @@ export function SectionHeader({
|
|||
return (
|
||||
<div
|
||||
onClick={onToggleCollapse}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "10px 16px",
|
||||
borderBottom: isCollapsed ? "none" : "1px solid #f0f0f0",
|
||||
background: "#fafafa",
|
||||
cursor: onToggleCollapse ? "pointer" : "default",
|
||||
transition: "background 0.15s ease",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (onToggleCollapse) {
|
||||
e.currentTarget.style.background = "#f5f5f5";
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = "#fafafa";
|
||||
}}
|
||||
className={cn(
|
||||
"flex items-center justify-between bg-muted px-4 py-2.5 transition-colors",
|
||||
isCollapsed ? "border-b-0" : "border-b border-border",
|
||||
onToggleCollapse ? "cursor-pointer hover:bg-accent" : "cursor-default",
|
||||
)}
|
||||
>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 16 }}>
|
||||
{/* Collapse Arrow */}
|
||||
{onToggleCollapse && (
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
{isCollapsed ? (
|
||||
<DownOutlined style={{ fontSize: 10, color: "#8c8c8c" }} />
|
||||
) : (
|
||||
<UpOutlined style={{ fontSize: 10, color: "#8c8c8c" }} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Icon + Label */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||
{type === "input" ? (
|
||||
<MessageOutlined style={{ color: "#8c8c8c", fontSize: 14 }} />
|
||||
<div className="flex items-center gap-4">
|
||||
{onToggleCollapse &&
|
||||
(isCollapsed ? (
|
||||
<ChevronDown className="size-2.5 text-muted-foreground" />
|
||||
) : (
|
||||
<span style={{ fontSize: 14, filter: "grayscale(1)", opacity: 0.6 }}>✨</span>
|
||||
<ChevronUp className="size-2.5 text-muted-foreground" />
|
||||
))}
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{type === "input" ? (
|
||||
<MessageSquare className="size-3.5 text-muted-foreground" />
|
||||
) : (
|
||||
<span className="text-sm opacity-60 grayscale">✨</span>
|
||||
)}
|
||||
<Text style={{ fontWeight: 500, fontSize: 14 }}>{type === "input" ? "Input" : "Output"}</Text>
|
||||
<span className="text-sm font-medium">{type === "input" ? "Input" : "Output"}</span>
|
||||
</div>
|
||||
|
||||
{/* Tokens */}
|
||||
{tokens !== undefined && (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
Tokens: {tokens.toLocaleString()}
|
||||
</Text>
|
||||
<span className="text-xs text-muted-foreground">Tokens: {tokens.toLocaleString()}</span>
|
||||
)}
|
||||
|
||||
{/* Cost */}
|
||||
{cost !== undefined && (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
Cost: ${cost.toFixed(6)}
|
||||
</Text>
|
||||
)}
|
||||
{cost !== undefined && <span className="text-xs text-muted-foreground">Cost: ${cost.toFixed(6)}</span>}
|
||||
|
||||
{/* Turn count */}
|
||||
{turnCount !== undefined && turnCount > 0 && (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
Turns: {turnCount}
|
||||
</Text>
|
||||
<span className="text-xs text-muted-foreground">Turns: {turnCount}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Copy Button */}
|
||||
<Tooltip title="Copy">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(); // Prevent triggering collapse
|
||||
onCopy();
|
||||
}}
|
||||
/>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
aria-label="Copy"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onCopy();
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Copy />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>Copy</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@
|
|||
* and indicates which ones were actually called in the response
|
||||
*/
|
||||
|
||||
import { Collapse, Typography } from "antd";
|
||||
import { useState } from "react";
|
||||
import { ChevronDown, ChevronRight } from "lucide-react";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { LogEntry } from "../columns";
|
||||
import { parseToolsFromLog } from "./utils";
|
||||
import { ToolItem } from "./ToolItem";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface ToolsSectionProps {
|
||||
log: LogEntry;
|
||||
}
|
||||
|
||||
export function ToolsSection({ log }: ToolsSectionProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const tools = parseToolsFromLog(log);
|
||||
|
||||
// Don't render if no tools
|
||||
|
|
@ -32,34 +33,33 @@ export function ToolsSection({ log }: ToolsSectionProps) {
|
|||
const hasMoreTools = tools.length > 2;
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow-sm w-full max-w-full overflow-hidden mb-6">
|
||||
<Collapse
|
||||
expandIconPosition="start"
|
||||
items={[
|
||||
{
|
||||
key: "1",
|
||||
label: (
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
|
||||
<h3 className="text-lg font-medium text-gray-900">Tools</h3>
|
||||
<Text type="secondary" style={{ fontSize: 14 }}>
|
||||
{totalTools} provided, {calledTools} called
|
||||
</Text>
|
||||
<Text type="secondary" style={{ fontSize: 14 }}>
|
||||
• {toolNamePreview}
|
||||
{hasMoreTools && "..."}
|
||||
</Text>
|
||||
</div>
|
||||
),
|
||||
children: (
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
||||
{tools.map((tool) => (
|
||||
<ToolItem key={tool.name} tool={tool} />
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<div className="mb-6 w-full max-w-full overflow-hidden rounded-lg bg-background shadow-sm">
|
||||
<Collapsible open={open} onOpenChange={setOpen}>
|
||||
<CollapsibleTrigger className="flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-muted">
|
||||
{open ? (
|
||||
<ChevronDown className="size-3.5 shrink-0 text-muted-foreground" />
|
||||
) : (
|
||||
<ChevronRight className="size-3.5 shrink-0 text-muted-foreground" />
|
||||
)}
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<h3 className="text-lg font-medium text-foreground">Tools</h3>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{totalTools} provided, {calledTools} called
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
• {toolNamePreview}
|
||||
{hasMoreTools && "..."}
|
||||
</span>
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<div className="flex flex-col gap-2 px-4 pb-4">
|
||||
{tools.map((tool) => (
|
||||
<ToolItem key={tool.name} tool={tool} />
|
||||
))}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue