diff --git a/apps/web/src/components/chat/MessagesTimeline.test.tsx b/apps/web/src/components/chat/MessagesTimeline.test.tsx index 7462ac0a..c92c71f1 100644 --- a/apps/web/src/components/chat/MessagesTimeline.test.tsx +++ b/apps/web/src/components/chat/MessagesTimeline.test.tsx @@ -791,8 +791,8 @@ describe("MessagesTimeline", () => { expect(markup).toContain("Claude API connection issue"); expect(markup).toContain("Runtime error"); - expect(markup).toContain("size-[6px] rounded-full bg-warning"); - expect(markup).toContain("size-[6px] rounded-full bg-destructive"); + expect(markup).toContain("size-[5px] rounded-full bg-warning"); + expect(markup).toContain("size-[5px] rounded-full bg-destructive"); expect(markup).not.toContain("border-warning/65"); expect(markup).not.toContain("border-destructive/70"); expect(markup).not.toContain("lucide-circle-alert"); diff --git a/apps/web/src/components/chat/ThreadActivityPopover.tsx b/apps/web/src/components/chat/ThreadActivityPopover.tsx index 0237c1e9..5304aa4a 100644 --- a/apps/web/src/components/chat/ThreadActivityPopover.tsx +++ b/apps/web/src/components/chat/ThreadActivityPopover.tsx @@ -10,11 +10,9 @@ import { } from "react"; import { ChevronDownIcon, - ClockIcon, ExternalLinkIcon, FileTextIcon, ListTodoIcon, - LoaderIcon, RadarIcon, SquareIcon, TerminalSquareIcon, @@ -28,7 +26,13 @@ import { cn } from "~/lib/utils"; import { useHorizontalOverflow } from "../../hooks/useHorizontalOverflow"; import { Button } from "../ui/button"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; -import { SpineNode, SpineRow, spineAccentRowStyle, type SpineNodeKind } from "../ui/threadline"; +import { + LiveNode, + SpineNode, + SpineRow, + spineAccentRowStyle, + type SpineNodeKind, +} from "../ui/threadline"; import { Tooltip, TooltipPopup, TooltipTrigger, TooltipWrapper } from "../ui/tooltip"; import { backgroundRunCommandText, @@ -530,11 +534,7 @@ function TaskSection({ nodeOffset={TASK_STEP_NODE_OFFSET_PX} connectTop={index > 0} connectBottom={index < visiblePlanStepRows.length - 1} - style={ - liveStepIndex >= 0 - ? spineAccentRowStyle(Math.abs(index - liveStepIndex)) - : undefined - } + style={liveStepIndex >= 0 ? spineAccentRowStyle(liveStepIndex - index) : undefined} >
{backgroundRuns.length}
-
- {backgroundRuns.map((run) => { - const metaItems = backgroundRunMetaItems(run); + {/* Runs are rows on their own spine, drawn the same way as the task + steps above so the popover reads as one surface. Every run is live, + so each row carries the halo node. */} +
+ {backgroundRuns.map((run, index) => { + const metaItems = [backgroundRunSourceLabel(run), ...backgroundRunMetaItems(run)]; const commandText = backgroundRunCommandText(run); const showCommandText = isInformativeBackgroundRunCommand(commandText); const primaryUrl = run.urls[0] ?? null; const extraUrlCount = Math.max(0, run.urls.length - 1); return ( -
} + nodeOffset={TASK_STEP_NODE_OFFSET_PX} + connectTop={index > 0} + connectBottom={index < backgroundRuns.length - 1} > -
- - - -
-
-
- {run.label} -
-
- - {run.statusLabel} - - {run.terminalId ? ( - - - - ) : null} - {run.canStop ? ( - - - - ) : null} -
+
+
+
+ {run.label}
- -
- - {backgroundRunSourceLabel(run)} - - {metaItems.map((item) => ( - + {run.statusLabel} + + {run.terminalId ? ( + +
+
- {primaryUrl || showCommandText ? ( -
- {primaryUrl ? ( - - ) : null} - {showCommandText ? ( - -
- {commandText} -
-
+
+ {metaItems.map((item, itemIndex) => ( + + {itemIndex > 0 ? ( + ) : null} -
- ) : null} + 0 ? "font-mono" : undefined}>{item} + + ))}
+ + {primaryUrl ? ( + + ) : null} + {showCommandText ? ( + +
+ {commandText} +
+
+ ) : null}
-
+ ); })}
diff --git a/apps/web/src/components/ui/threadline.tsx b/apps/web/src/components/ui/threadline.tsx index b0cc06c8..8b283b94 100644 --- a/apps/web/src/components/ui/threadline.tsx +++ b/apps/web/src/components/ui/threadline.tsx @@ -123,25 +123,29 @@ function SpineRow({ }) { return (
-
+ {/* Whole-pixel geometry: the 1px line sits at x=7 (no transform, so the + browser cannot snap it to a neighbouring column) and the node is + centred in a 15px box, i.e. on x=7.5, the line's own centre. Odd node + sizes then land every edge on a whole pixel. */} +
{connectTop ? (