Give the traceback button its width back

Reserving a slot for all three status controls left 72px for a node's title,
against about 140px before. Only the stop button and the dot come and go on
their own; the traceback button appears when a node newly fails and goes when
someone acknowledges it, which is a thing to notice rather than a flicker. It
goes back in the row, and the title gets 106px.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZeGnqVsf5VHQqvz4HdUhN
This commit is contained in:
2026-08-23 09:28:25 +02:00
co-authored by Claude Opus 5
parent b9922e7a7d
commit 163847cdc1
+48 -47
View File
@@ -226,11 +226,14 @@ function FlowNodeComponent({ data, selected }: NodeProps) {
{typeLabel} {typeLabel}
</span> </span>
</span> </span>
{/* Each control sits in a slot that is there whether the control {/* This and the dot below sit in slots that are there whether the
is or not. They come and go with what the node is doing — and a control is or not: both come and go on their own — a node running
node running many times a second comes and goes that often — so many times a second mounts and unmounts this on every execution —
in the flex row itself they would resize the card on every and in the flex row itself that resizes the card each time, which
execution, which reads as a flickering shape. */} reads as a flickering shape. The traceback button below is left
in the row on purpose: it appears when a node newly fails and
goes when someone acknowledges it, which is a thing to notice
rather than a flicker, and a slot for it costs the title 34px. */}
<span className="flex size-6 shrink-0 items-center justify-center"> <span className="flex size-6 shrink-0 items-center justify-center">
{running ? ( {running ? (
<Tooltip> <Tooltip>
@@ -259,48 +262,46 @@ function FlowNodeComponent({ data, selected }: NodeProps) {
) : null} ) : null}
</span> </span>
<span className="flex size-6 shrink-0 items-center justify-center"> {(status === "error" || failedEarlier) && onShowLogs ? (
{(status === "error" || failedEarlier) && onShowLogs ? ( <Tooltip>
<Tooltip> <TooltipTrigger asChild>
<TooltipTrigger asChild> <Button
<Button variant="ghost"
variant="ghost" size="icon-sm"
size="icon-sm" // `nodrag` keeps xyflow from reading the press as a drag; the
// `nodrag` keeps xyflow from reading the press as a drag; the // click itself is stopped so the node panel stays closed.
// click itself is stopped so the node panel stays closed. className={cn(
className={cn( "nodrag nopan size-6 shrink-0 hover:text-destructive",
"nodrag nopan size-6 shrink-0 hover:text-destructive", // Red while it is the only thing left saying so, and named
// Red while it is the only thing left saying so, and named // in words beside it: colour never carries a status alone.
// in words beside it: colour never carries a status alone. failedEarlier
failedEarlier ? "text-destructive"
? "text-destructive" : "text-muted-foreground",
: "text-muted-foreground", )}
)} aria-label={
aria-label={ failedEarlier
failedEarlier ? `Failed at ${failedAt} — show the traceback`
? `Failed at ${failedAt} — show the traceback` : "Show what this node printed"
: "Show what this node printed" }
} data-testid="node-traceback"
data-testid="node-traceback" onClick={(event) => {
onClick={(event) => { event.stopPropagation()
event.stopPropagation() onShowLogs(definition.id)
onShowLogs(definition.id) // Reading it is what dismisses it: nothing else does, and a
// Reading it is what dismisses it: nothing else does, and a // marker that never goes away stops meaning anything.
// marker that never goes away stops meaning anything. liveStore.acknowledgeFailure(nodeId)
liveStore.acknowledgeFailure(nodeId) }}
}} >
> <Bug />
<Bug /> </Button>
</Button> </TooltipTrigger>
</TooltipTrigger> <TooltipContent>
<TooltipContent> {failedEarlier
{failedEarlier ? `Failed at ${failedAt} — show the traceback`
? `Failed at ${failedAt} — show the traceback` : "Show the traceback"}
: "Show the traceback"} </TooltipContent>
</TooltipContent> </Tooltip>
</Tooltip> ) : null}
) : null}
</span>
<span className="flex size-2 shrink-0 items-center justify-center"> <span className="flex size-2 shrink-0 items-center justify-center">
{style ? ( {style ? (