From 1a3a92bd1b12fc91fbb5541998a288686daabf72 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Fri, 10 Apr 2026 19:09:03 +0700 Subject: [PATCH] fix: fix 4px layout shift on streaming commit in chat (#24203) Closes CODAGT-124 When a streaming assistant response finishes and moves from the live stream tail into the conversation timeline, the message jumps 4px upward. This happens because the outer layout wrapper and live-stream section both used `gap-3` (12px), while the committed-message list used `gap-2` (8px). Unify all three containers to `gap-2` so the gap between messages stays at 8px regardless of whether they're streaming or committed, eliminating the layout shift. A Storybook story with play-function assertions locks the invariant: it renders both committed messages and an active stream, then verifies both the outer and inner containers report `rowGap === "8px"`. --- .../AgentsPage/AgentChatPageView.stories.tsx | 30 +++++++++++++++++++ .../ChatConversation/ConversationTimeline.tsx | 2 +- .../ChatConversation/LiveStreamTail.tsx | 2 +- .../AgentsPage/components/ChatPageContent.tsx | 5 +++- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx b/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx index dee306b92e..2b1837bfd3 100644 --- a/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx +++ b/site/src/pages/AgentsPage/AgentChatPageView.stories.tsx @@ -474,6 +474,16 @@ const buildStoreWithMessages = ( return store; }; +const gapTestStore = createChatStore(); +gapTestStore.replaceMessages([ + buildMessage(1, "user", "Explain the layout."), + buildMessage(2, "assistant", "Here is the explanation."), + buildMessage(3, "user", "Can you elaborate?"), +]); +gapTestStore.applyMessageParts([ + { type: "text", text: "Certainly, here are more details..." }, +]); + // --------------------------------------------------------------------------- // Editing flow stories // --------------------------------------------------------------------------- @@ -521,6 +531,26 @@ export const EditingSaving: Story = { ), }; +export const ConsistentGapBetweenTimelineAndStream: Story = { + render: () => , + play: async ({ canvasElement }) => { + const wrapper = canvasElement.querySelector( + '[data-testid="chat-timeline-wrapper"]', + ); + expect(wrapper).not.toBeNull(); + + const outerGap = window.getComputedStyle(wrapper!).rowGap; + expect(outerGap).toBe("8px"); + + const timeline = wrapper!.querySelector( + '[data-testid="conversation-timeline"]', + ); + expect(timeline).not.toBeNull(); + const innerGap = window.getComputedStyle(timeline!).rowGap; + expect(innerGap).toBe("8px"); + }, +}; + // --------------------------------------------------------------------------- // AgentChatPageNotFoundView stories // --------------------------------------------------------------------------- diff --git a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx index 98c1367dbd..0db14d35dd 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx @@ -1041,7 +1041,7 @@ export const ConversationTimeline = memo( } return ( -
+
{parsedMessages.map(({ message, parsed }, msgIdx) => { if (message.role === "user") { return ( diff --git a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx index b29a4a5f6c..f45a8d15b8 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.tsx @@ -70,7 +70,7 @@ export const LiveStreamTailContent = ({ } return ( -
+
{shouldRenderEmptyState && (

Start a conversation with your agent.

diff --git a/site/src/pages/AgentsPage/components/ChatPageContent.tsx b/site/src/pages/AgentsPage/components/ChatPageContent.tsx index 760e647c5f..609961eec9 100644 --- a/site/src/pages/AgentsPage/components/ChatPageContent.tsx +++ b/site/src/pages/AgentsPage/components/ChatPageContent.tsx @@ -86,7 +86,10 @@ export const ChatPageTimeline: FC = ({ return ( -
+
{/* VNC sessions for completed agents may already be terminated, so inline desktop previews are disabled via showDesktopPreviews={false} to avoid a perpetual