From fdc9b3a7e442f9b68896ec7e86a978ad252fc3c9 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 25 Mar 2026 10:37:55 -0400 Subject: [PATCH] fix: match text and image attachment heights in conversation timeline (#23593) ## Problem Text attachments (`InlineTextAttachmentButton`) and image thumbnails (`ImageThumbnail`) rendered at different heights when displayed side by side in user messages. Text cards had no explicit height (content-driven), while images used `h-16` (64px). ## Changes **`ConversationTimeline.tsx`** - Added `h-16` to `InlineTextAttachmentButton` to match `ImageThumbnail` - Added `isPlaceholder` prop: when the content hasn't been fetched yet (file_id path), renders "Pasted text" in sans-serif `text-sm` with `items-center` alignment instead of monospace `text-xs` - Once real content loads, it still renders in `font-mono text-xs` with `formatTextAttachmentPreview()` **`ConversationTimeline.stories.tsx`** - Added `UserMessageWithMixedAttachments` story showing a text attachment and image side by side as a visual regression guard --- .../ConversationTimeline.stories.tsx | 36 +++++++++++++++++++ .../AgentDetail/ConversationTimeline.tsx | 17 ++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.stories.tsx b/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.stories.tsx index e6354e3493..9986a63714 100644 --- a/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.stories.tsx +++ b/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.stories.tsx @@ -299,6 +299,42 @@ export const UserMessageWithTextAttachmentOnly: Story = { }, }; +/** Visual regression: text and image attachments render at the same height. */ +export const UserMessageWithMixedAttachments: Story = { + args: { + ...defaultArgs, + parsedMessages: parseMessagesWithMergedTools([ + { + ...baseMessage, + id: 1, + role: "user", + content: [ + { type: "text", text: "Here is a screenshot and some context" }, + { + type: "file", + media_type: "image/png", + data: TEST_PNG_B64, + }, + { + type: "file", + file_id: "storybook-test-text", + media_type: "text/plain", + }, + ], + }, + ]), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const images = canvas.getAllByRole("img", { name: "Attached image" }); + expect(images).toHaveLength(1); + const textButtons = await canvas.findAllByRole("button", { + name: "View text attachment", + }); + expect(textButtons).toHaveLength(1); + }, +}; + /** Text-only messages must not produce spurious image thumbnails. */ export const UserMessageTextOnly: Story = { args: { diff --git a/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.tsx b/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.tsx index 55432f1916..3d470ff083 100644 --- a/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.tsx +++ b/site/src/pages/AgentsPage/components/AgentDetail/ConversationTimeline.tsx @@ -123,20 +123,26 @@ const SmoothedResponse: FC<{ const InlineTextAttachmentButton: FC<{ content: string; onPreview?: (content: string) => void; -}> = ({ content, onPreview }) => { + isPlaceholder?: boolean; +}> = ({ content, onPreview, isPlaceholder }) => { return ( ); @@ -156,6 +162,7 @@ const TextAttachmentButton: FC<{ return ( { if (content !== null) { onPreview?.(content);