From 3def04a3ee2151d498f3d07da7d76ffedad15526 Mon Sep 17 00:00:00 2001 From: Jeremy Ruppel Date: Thu, 2 Apr 2026 09:58:18 -0400 Subject: [PATCH] fix(site): use overflow-hidden for prompt text overflow (#23977) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also had Claude write a couple of stories for the SessionTimeline 🤖 but they look good --- .../SessionTimeline.stories.tsx | 128 ++++++++++++++++++ .../SessionTimeline/SessionTimeline.tsx | 2 +- 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.stories.tsx diff --git a/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.stories.tsx b/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.stories.tsx new file mode 100644 index 0000000000..e07d543d3b --- /dev/null +++ b/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.stories.tsx @@ -0,0 +1,128 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import type { AIBridgeThread } from "#/api/typesGenerated"; +import { MockSession } from "#/testHelpers/entities"; +import { SessionTimeline } from "./SessionTimeline"; + +// A thread with one thinking block and one tool call. +const mockThread: AIBridgeThread = { + id: "thread-1", + prompt: + "Can you check what files are in the project and summarize the structure?", + model: "claude-opus-4-6", + provider: "anthropic", + started_at: "2026-03-09T09:28:15.000Z", + ended_at: "2026-03-09T09:28:47.000Z", + token_usage: { + input_tokens: 1240, + output_tokens: 320, + metadata: { cache_read_input_tokens: 900 }, + }, + agentic_actions: [ + { + model: "claude-opus-4-6", + token_usage: { + input_tokens: 620, + output_tokens: 160, + metadata: {}, + }, + thinking: [ + { + text: "The user wants to understand the project structure. I should start by listing the root directory, then drill into interesting sub-directories.", + }, + ], + tool_calls: [ + { + id: "tool-1", + interception_id: "interception-1", + provider_response_id: "resp-1", + server_url: "http://localhost:3000/mcp", + tool: "list_directory", + injected: false, + input: JSON.stringify({ path: "." }), + metadata: {}, + created_at: "2026-03-09T09:28:20.000Z", + }, + ], + }, + ], +}; + +// A second thread with a long prompt and multiple tool calls. +const mockThreadLong: AIBridgeThread = { + id: "thread-2", + prompt: + "Please refactor the authentication module so that it uses the new token-based flow we discussed. Make sure to update all the related tests and add inline comments explaining the security rationale for each change.", + model: "claude-opus-4-6", + provider: "anthropic", + started_at: "2026-03-09T10:00:00.000Z", + ended_at: "2026-03-09T10:05:30.000Z", + token_usage: { + input_tokens: 8500, + output_tokens: 3200, + metadata: { + cache_read_input_tokens: 6000, + cache_creation_input_tokens: 2000, + }, + }, + agentic_actions: [ + { + model: "claude-opus-4-6", + token_usage: { input_tokens: 2800, output_tokens: 1100, metadata: {} }, + thinking: [], + tool_calls: [ + { + id: "tool-2a", + interception_id: "interception-2", + provider_response_id: "resp-2", + server_url: "http://localhost:3000/mcp", + tool: "read_file", + injected: false, + input: JSON.stringify({ path: "src/auth/index.ts" }), + metadata: {}, + created_at: "2026-03-09T10:00:15.000Z", + }, + { + id: "tool-2b", + interception_id: "interception-3", + provider_response_id: "resp-3", + server_url: "http://localhost:3000/mcp", + tool: "write_file", + injected: false, + input: JSON.stringify({ + path: "src/auth/index.ts", + content: "// refactored auth module\n...", + }), + metadata: {}, + created_at: "2026-03-09T10:01:00.000Z", + }, + ], + }, + ], +}; + +const noop = () => {}; + +const meta: Meta = { + title: "pages/AIBridgePage/SessionTimeline", + component: SessionTimeline, + args: { + initiator: MockSession.initiator, + threads: [mockThread], + hasNextPage: false, + isFetchingNextPage: false, + onFetchNextPage: noop, + }, +}; + +export default meta; +type Story = StoryObj; + +export const OneThread: Story = {}; + +export const MultipleThreads: Story = { + args: { threads: [mockThread, mockThreadLong] }, +}; + +export const FetchingNextPage: Story = { + args: { hasNextPage: true, isFetchingNextPage: true }, +}; diff --git a/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.tsx b/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.tsx index 3c724ce7d6..2cbb9747d6 100644 --- a/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.tsx +++ b/site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.tsx @@ -62,7 +62,7 @@ const ExpandableText: FC = ({ } : undefined } - className={cn(className, "overflow-scroll", isExpanded && "pb-9")} + className={cn(className, "overflow-hidden", isExpanded && "pb-9")} > {text}