fix: move tool elapsed time to stable badge before chevron (#124)

Extract the elapsed time from the tool title string into a separate
`tabular-nums` badge rendered before the chevron. This prevents the
title text and subsequent elements from shifting each second as the
number width changes.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Toohey
2026-04-08 17:21:20 +10:00
committed by GitHub
parent 1fb4429b42
commit 29dfc25b51
2 changed files with 11 additions and 3 deletions
@@ -217,8 +217,8 @@ export function ToolCallAdapter({
const elapsed = useElapsedTime(status, startedAt);
const state = toolStatusMap[status];
const title =
status === "executing" && elapsed >= 3 ? `${name} (${elapsed}s)` : name;
const elapsedSeconds =
status === "executing" && elapsed >= 3 ? elapsed : undefined;
return (
<div>
@@ -226,9 +226,10 @@ export function ToolCallAdapter({
<ToolHeader
type="dynamic-tool"
toolName={name}
title={title}
title={name}
state={state}
showIcon={false}
elapsedSeconds={elapsedSeconds}
/>
<ToolContent>
{Object.keys(args).length > 0 && <ToolInput input={args} />}
@@ -30,6 +30,7 @@ export type ToolHeaderProps = {
title?: string;
className?: string;
showIcon?: boolean;
elapsedSeconds?: number;
} & (
| { type: ToolUIPart["type"]; state: ToolUIPart["state"]; toolName?: never }
| {
@@ -76,6 +77,7 @@ export const ToolHeader = ({
state,
toolName,
showIcon = true,
elapsedSeconds,
...props
}: ToolHeaderProps) => {
const derivedName =
@@ -89,6 +91,11 @@ export const ToolHeader = ({
{showIcon && <WrenchIcon className="size-4 text-muted-foreground" />}
<span className="font-medium text-sm">{title ?? derivedName}</span>
{getStatusBadge(state)}
{elapsedSeconds != null && (
<span className="tabular-nums text-xs text-muted-foreground">
{elapsedSeconds}s
</span>
)}
<ChevronDownIcon className="size-3.5 text-muted-foreground transition-transform group-data-[state=closed]:-rotate-90" />
</CollapsibleTrigger>
);