From 7f0b7d77f1ccb9fad5be9a0a7152055f20491f03 Mon Sep 17 00:00:00 2001 From: Shivam Sharma <91240327+shivamhwp@users.noreply.github.com> Date: Tue, 24 Mar 2026 07:05:51 +0530 Subject: [PATCH] Collapse work log groups by default --- .../components/chat/MessagesTimeline.test.tsx | 114 +++++++++++++++--- .../src/components/chat/MessagesTimeline.tsx | 51 ++++---- 2 files changed, 120 insertions(+), 45 deletions(-) diff --git a/apps/web/src/components/chat/MessagesTimeline.test.tsx b/apps/web/src/components/chat/MessagesTimeline.test.tsx index e694faa0f2..2634bcadea 100644 --- a/apps/web/src/components/chat/MessagesTimeline.test.tsx +++ b/apps/web/src/components/chat/MessagesTimeline.test.tsx @@ -43,15 +43,34 @@ beforeAll(() => { }); describe("MessagesTimeline", () => { + const baseProps = { + hasMessages: true, + isWorking: false, + activeTurnInProgress: false, + activeTurnStartedAt: null, + scrollContainer: null, + completionDividerBeforeEntryId: null, + completionSummary: null, + turnDiffSummaryByAssistantMessageId: new Map(), + nowIso: "2026-03-17T19:12:30.000Z", + expandedWorkGroups: {}, + onToggleWorkGroup: () => {}, + onOpenTurnDiff: () => {}, + revertTurnCountByUserMessageId: new Map(), + onRevertUserMessage: () => {}, + isRevertingCheckpoint: false, + onImageExpand: () => {}, + markdownCwd: undefined, + resolvedTheme: "light" as const, + timestampFormat: "locale" as const, + workspaceRoot: undefined, + }; + it("renders inline terminal labels with the composer chip UI", async () => { const { MessagesTimeline } = await import("./MessagesTimeline"); const markup = renderToStaticMarkup( { }, }, ]} - completionDividerBeforeEntryId={null} - completionSummary={null} - turnDiffSummaryByAssistantMessageId={new Map()} - nowIso="2026-03-17T19:12:30.000Z" - expandedWorkGroups={{}} - onToggleWorkGroup={() => {}} - onOpenTurnDiff={() => {}} - revertTurnCountByUserMessageId={new Map()} - onRevertUserMessage={() => {}} - isRevertingCheckpoint={false} - onImageExpand={() => {}} - markdownCwd={undefined} - resolvedTheme="light" - timestampFormat="locale" - workspaceRoot={undefined} />, ); @@ -96,4 +100,74 @@ describe("MessagesTimeline", () => { expect(markup).toContain("lucide-terminal"); expect(markup).toContain("yoo what's "); }); + + it("renders tool call groups collapsed by default", async () => { + const { MessagesTimeline } = await import("./MessagesTimeline"); + const markup = renderToStaticMarkup( + , + ); + + expect(markup).toContain("Tool calls (1)"); + expect(markup).toContain("lucide-chevron-down"); + expect(markup).not.toContain("Ran command"); + expect(markup).not.toContain("bun lint"); + }); + + it("renders expanded work log groups with their entries", async () => { + const { MessagesTimeline } = await import("./MessagesTimeline"); + const markup = renderToStaticMarkup( + , + ); + + expect(markup).toContain("Work log (2)"); + expect(markup).toContain("Approval resolved"); + expect(markup).toContain("Command approved"); + expect(markup).toContain("Tool call"); + expect(markup).toContain("Read: /tmp/app.ts"); + }); }); diff --git a/apps/web/src/components/chat/MessagesTimeline.tsx b/apps/web/src/components/chat/MessagesTimeline.tsx index f3e462f7fe..f50f81d224 100644 --- a/apps/web/src/components/chat/MessagesTimeline.tsx +++ b/apps/web/src/components/chat/MessagesTimeline.tsx @@ -22,6 +22,7 @@ import ChatMarkdown from "../ChatMarkdown"; import { BotIcon, CheckIcon, + ChevronDownIcon, CircleAlertIcon, EyeIcon, GlobeIcon, @@ -43,6 +44,7 @@ import { DiffStatLabel, hasNonZeroStat } from "./DiffStatLabel"; import { MessageCopyButton } from "./MessageCopyButton"; import { computeMessageDurationStart, normalizeCompactToolLabel } from "./MessagesTimeline.logic"; import { TerminalContextInlineChip } from "./TerminalContextInlineChip"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible"; import { deriveDisplayedUserMessageState, type ParsedTerminalContextEntry, @@ -56,7 +58,6 @@ import { textContainsInlineTerminalContextLabels, } from "./userMessageTerminalContexts"; -const MAX_VISIBLE_WORK_LOG_ENTRIES = 6; const ALWAYS_UNVIRTUALIZED_TAIL_ROWS = 8; interface MessagesTimelineProps { @@ -315,40 +316,40 @@ export const MessagesTimeline = memo(function MessagesTimeline({ const groupId = row.id; const groupedEntries = row.groupedEntries; const isExpanded = expandedWorkGroups[groupId] ?? false; - const hasOverflow = groupedEntries.length > MAX_VISIBLE_WORK_LOG_ENTRIES; - const visibleEntries = - hasOverflow && !isExpanded - ? groupedEntries.slice(-MAX_VISIBLE_WORK_LOG_ENTRIES) - : groupedEntries; - const hiddenCount = groupedEntries.length - visibleEntries.length; const onlyToolEntries = groupedEntries.every((entry) => entry.tone === "tool"); - const showHeader = hasOverflow || !onlyToolEntries; const groupLabel = onlyToolEntries ? "Tool calls" : "Work log"; return ( -
- {showHeader && ( -
+ onToggleWorkGroup(groupId)} + open={isExpanded} + > + +

{groupLabel} ({groupedEntries.length})

- {hasOverflow && ( - +
+
+ +
+ {groupedEntries.map((workEntry) => ( + + ))}
- )} -
- {visibleEntries.map((workEntry) => ( - - ))} + +
+ {isExpanded ? `${groupLabel} expanded` : `${groupLabel} collapsed`}
-
+
); })()}