mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
- extract a shared CopyButton into components/ui.tsx and drop the install wizard's local duplicate - sticky stage header at the top of the turn stream so users always know which stage they're reading as they scroll - copy-to-clipboard button on System, Assistant, and Command blocks; revealed on hover/focus - stdout/stderr longer than 20 lines collapse to the last 20 with a "Show N earlier lines" expander - bump the [10px] labels in tool-use.tsx to [11px] for readability Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { useState } from "react";
|
|
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
|
import { WrenchScrewdriverIcon } from "@heroicons/react/24/outline";
|
|
|
|
export interface ToolUse {
|
|
id: string;
|
|
toolName: string;
|
|
input: string;
|
|
result: string;
|
|
isError: boolean;
|
|
durationMs?: number;
|
|
}
|
|
|
|
export function ToolRow({ tool }: { tool: ToolUse }) {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<div className="border-b border-line last:border-b-0">
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpen((v) => !v)}
|
|
className="flex w-full items-center gap-1.5 px-2.5 py-1.5 text-left transition-colors hover:bg-overlay"
|
|
>
|
|
<ChevronRightIcon className={`size-3 shrink-0 text-fg-muted transition-transform duration-150 ${open ? "rotate-90" : ""}`} />
|
|
<WrenchScrewdriverIcon className="size-3.5 shrink-0 text-fg-muted" />
|
|
<span className="font-mono text-xs text-fg-3">{tool.toolName}</span>
|
|
{tool.durationMs != null && <span className="text-[11px] text-fg-muted">{tool.durationMs}ms</span>}
|
|
<span className="truncate font-mono text-xs text-fg-muted">{tool.input}</span>
|
|
</button>
|
|
{open && (
|
|
<div className="space-y-px bg-overlay px-2.5 pb-2 pt-1">
|
|
<div className="rounded bg-overlay px-2.5 py-2">
|
|
<div className="mb-1 text-[11px] font-medium uppercase tracking-wider text-fg-muted">Input</div>
|
|
<pre className="whitespace-pre-wrap font-mono text-xs leading-relaxed text-fg-3">{tool.input}</pre>
|
|
</div>
|
|
<div className="rounded bg-overlay px-2.5 py-2">
|
|
<div className="mb-1 text-[11px] font-medium uppercase tracking-wider text-fg-muted">Result</div>
|
|
<pre className={`whitespace-pre-wrap font-mono text-xs leading-relaxed ${tool.isError ? "text-coral" : "text-fg-3"}`}>{tool.result}</pre>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function ToolBlock({ tools }: { tools: ToolUse[] }) {
|
|
return (
|
|
<div className="rounded-md border border-line bg-overlay overflow-hidden">
|
|
{tools.map((tool) => (
|
|
<ToolRow key={tool.id} tool={tool} />
|
|
))}
|
|
</div>
|
|
);
|
|
}
|