mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline): hide "Session completed" until every thread has loaded (#26955)
> 🤖 This PR was written by Coder Agents on behalf of Jake Howell. The "Session completed" marker at the bottom of an AI Gateway session timeline was rendered unconditionally, so on long sessions it appeared below still-loading threads while the user scrolled. That is misleading: users read it as the end of the session even when more threads are about to stream in. Only render the session end marker (rows 7 and 8 of the grid: the connecting vertical line, the success dot, and the "Session completed" text) once every thread has loaded, that is, once both `hasNextPage` and `isFetchingNextPage` are false. The dashed timeline box still closes cleanly at the bottom, and the infinite-scroll spinner keeps rendering inside row 5 while more pages fetch. | Old | New | | --- | --- | | <img width="1099" height="338" alt="preview-old-behaviour" src="https://github.com/user-attachments/assets/f86c9ce1-f4ca-4088-a1ed-9cdcf8fb940c" /> | <img width="1099" height="323" alt="preview-new-heaviour" src="https://github.com/user-attachments/assets/b4a1e703-10d2-4378-9f25-48cac46249a1" /> | ## Verification Rendered each SessionTimeline story via a headless Chromium and asserted whether "Session completed" is present: | Story | `hasNextPage` | `isFetchingNextPage` | "Session completed" | | --- | --- | --- | --- | | OneThread | false | false | visible | | MultipleThreads | false | false | visible | | FetchingNextPage | true | true | hidden | | HasMoreThreadsToLoad (new) | true | false | hidden | All checks pass locally: - `pnpm format` (no changes) - `pnpm lint:check` - `pnpm lint:types` - `make pre-commit` via githooks <details> <summary>Implementation notes</summary> - `site/src/pages/AIBridgePage/SessionThreadsPage/SessionTimeline/SessionTimeline.tsx`: wrap the row 7 spacer and row 8 status dot/text in `!hasNextPage && !isFetchingNextPage`. - `SessionTimeline.stories.tsx`: add `HasMoreThreadsToLoad` to cover the between-fetches state. - No prop signature or public API change; `SessionTimelineSkeleton.tsx` is untouched because the skeleton is only shown before any threads have loaded. </details>
This commit is contained in:
+10
@@ -142,3 +142,13 @@ export const MultipleThreads: Story = {
|
||||
export const FetchingNextPage: Story = {
|
||||
args: { hasNextPage: true, isFetchingNextPage: true },
|
||||
};
|
||||
|
||||
// The "Session completed" marker should stay hidden while more threads
|
||||
// remain to be loaded so it cannot be misread as the end of the session.
|
||||
export const HasMoreThreadsToLoad: Story = {
|
||||
args: {
|
||||
threads: [mockThread, mockThreadLong],
|
||||
hasNextPage: true,
|
||||
isFetchingNextPage: false,
|
||||
},
|
||||
};
|
||||
|
||||
+24
-16
@@ -563,23 +563,31 @@ export const SessionTimeline: FC<SessionTimelineProps> = ({
|
||||
{/* bottom right rounded corner */}
|
||||
</div>
|
||||
|
||||
{/* row 7: sized intentionally to create the visual space below the timeline border */}
|
||||
<div className="row-start-7 col-start-3 border-0 border-l border-t border-solid h-4">
|
||||
{/* vertical line */}
|
||||
</div>
|
||||
{/* rows 7-8: session end marker. Only rendered once every thread
|
||||
has loaded so "Session completed" cannot appear below
|
||||
still-loading threads and be mistaken for the end of the
|
||||
session. */}
|
||||
{!hasNextPage && !isFetchingNextPage && (
|
||||
<>
|
||||
{/* row 7: sized intentionally to create the visual space below the timeline border */}
|
||||
<div className="row-start-7 col-start-3 border-0 border-l border-t border-solid h-4">
|
||||
{/* vertical line */}
|
||||
</div>
|
||||
|
||||
{/* row 8: session completed */}
|
||||
<div className="row-start-8 col-start-2 relative">
|
||||
<StatusIndicatorDot
|
||||
variant="success"
|
||||
className="absolute right-0 translate-x-1/2 translate-y-1/2"
|
||||
/>
|
||||
</div>
|
||||
<div className="row-start-8 col-start-4 flex items-center">
|
||||
<span className="text-content-success font-normal ml-4 text-sm py-1">
|
||||
Session completed
|
||||
</span>
|
||||
</div>
|
||||
{/* row 8: session completed */}
|
||||
<div className="row-start-8 col-start-2 relative">
|
||||
<StatusIndicatorDot
|
||||
variant="success"
|
||||
className="absolute right-0 translate-x-1/2 translate-y-1/2"
|
||||
/>
|
||||
</div>
|
||||
<div className="row-start-8 col-start-4 flex items-center">
|
||||
<span className="text-content-success font-normal ml-4 text-sm py-1">
|
||||
Session completed
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user