refactor(ui): migrate SectionHeader and ToolsSection to shadcn

This commit is contained in:
Yuneng Jiang 2026-08-13 09:39:37 -07:00
parent eb23dc2e81
commit bc9005c149
No known key found for this signature in database
3 changed files with 74 additions and 107 deletions

View file

@ -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
}
}
}
}

View file

@ -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>
);

View file

@ -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>
);
}