diff --git a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.stories.tsx b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.stories.tsx index c77a600819..210bfe4ce1 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.stories.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.stories.tsx @@ -896,3 +896,46 @@ export const MultiAssistantTurnCopyButton: Story = { expect(actions).toHaveLength(2); }, }; + +/** + * Regression: thinking-only assistant messages must have consistent + * bottom spacing before the next user bubble. A spacer div fills the + * gap that would normally come from the invisible action bar. + */ +export const ThinkingOnlyAssistantSpacing: Story = { + args: { + ...defaultArgs, + parsedMessages: buildMessages([ + { + ...baseMessage, + id: 1, + role: "user", + content: [{ type: "text", text: "Explain this code" }], + }, + { + ...baseMessage, + id: 2, + role: "assistant", + content: [ + { + type: "reasoning", + text: "Let me think about this step by step. The user wants me to explain the code they shared.", + }, + ], + }, + { + ...baseMessage, + id: 3, + role: "user", + content: [{ type: "text", text: "Any progress?" }], + }, + ]), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + // The thinking-only assistant message has no action bar, but + // it should still have visible text and a spacer element. + expect(canvas.getByText("Explain this code")).toBeInTheDocument(); + expect(canvas.getByText("Any progress?")).toBeInTheDocument(); + }, +}; diff --git a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx index f127733f42..98c1367dbd 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/ConversationTimeline.tsx @@ -669,6 +669,13 @@ const ChatMessageItem = memo<{ )} )} + {/* Spacer for assistant messages without an action bar + (e.g. thinking-only) so they have consistent bottom + padding before the next user bubble. */} + {!hideActions && + !isUser && + !hasCopyableContent && + Boolean(parsed.reasoning) &&
} {previewImage && (