Skip to content

feat(web,web-shared): redesign Streams view on the run detail page - #3159

Draft
mitul-s wants to merge 12 commits into
mainfrom
c+ms/streams-view-ui-improvements-1fe6
Draft

feat(web,web-shared): redesign Streams view on the run detail page#3159
mitul-s wants to merge 12 commits into
mainfrom
c+ms/streams-view-ui-improvements-1fe6

Conversation

@mitul-s

@mitul-s mitul-s commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Redesigns the Streams tab on the workflow run detail page so the reader can find the right stream, read what was written to it, and tell whether it is still producing data.

Stream identity (@workflow/web-shared, new describeStreamId helper)

  • Decodes opaque stream IDs into human-meaningful labels: strm_<ulid>_user → "Default stream", strm_<ulid>_user_<base64url(ns)> → the decoded namespace, strm_<id>_system_abort → "Abort signal". Unrecognized formats pass through verbatim.
  • The sidebar shows the label with the full stream ID beneath it (mono, truncated, full ID in the tooltip) instead of one truncated raw ID per row.

Stream viewer (@workflow/web-shared)

  • Unified header: stream identity + full ID on the left; live indicator, chunk count, and view controls on the right, replacing the two conditional stacked rows.
  • New Text view that reassembles string chunks into a readable transcript — the default for text-oriented streams (e.g. AI token streaming). Non-text chunks stay inspectable as quiet JSON blocks labeled by index; the Chunks view remains the lossless inspector (DataInspector).
  • Chunk ledger restyled from boxed cards into hairline-separated rows with a right-aligned tabular index gutter.
  • Follow-scroll preserves the reader's position: the tail is followed only while at the bottom; when new chunks arrive while scrolled up, a "New chunks" jump action appears instead of yanking the scroll position. Initial loads no longer prompt or scroll in Text view (starts at reading position).

Run detail page (@workflow/web)

  • The Streams sidebar fills the available panel height (drops the hard-coded max-h-[calc(100vh-400px)]), and the selected row gets aria-current.
  • The first stream auto-selects when the tab opens without a streamId URL param, so the first viewport shows data instead of an empty placeholder.

All styling stays on the existing Geist --ds-* tokens, works in light and dark themes, and the pulse animation respects prefers-reduced-motion.

Test plan

  • packages/web-shared: pnpm build, pnpm test (new stream-id.test.ts covers default/named/system/unknown/undecodable IDs; the two zstd-decoder failures are pre-existing on Node 22 — node:zlib lacks zstdCompressSync).
  • packages/web: pnpm build, pnpm test (94 passing).
  • Biome clean on all changed files (two pre-existing complexity warnings in run-detail-view.tsx unchanged).
  • Manual verification against a seeded local world (@workflow/web + world-local): screenshots in light and dark themes for default/named/system/live streams, narrow-viewport reflow, and scripted follow-scroll checks (pinned-at-bottom follows, scrolled-up prompts "New chunks", jump-to-latest works, initial load stays at reading position).

Changesets

Two changesets included (minor): @workflow/web-shared (viewer redesign) and @workflow/web (sidebar labels + auto-select).

Open in Web Open in Cursor 

…am identity

Decode opaque stream IDs (strm_<ulid>_user[_<base64url ns>], system abort
streams) into human-meaningful labels via a new describeStreamId helper,
and surface the identity in a unified viewer header with live status,
chunk count, and view controls.

Add a Text view that reassembles string chunks into a readable transcript
(the default for text-oriented streams, e.g. AI token streaming), keeping
non-text chunks inspectable as quiet JSON blocks. The raw chunk ledger is
restyled from boxed cards into hairline-separated rows with an aligned
index gutter.

Follow-scroll now preserves the reader's position: the tail is followed
only while at the bottom, and a jump-to-latest action appears when new
chunks arrive while scrolled up.
…rst stream

The sidebar now shows a human-meaningful label for each stream (decoded
namespace, Default stream, Abort signal) with the full stream ID beneath
it, fills the available panel height instead of a hard-coded max-height,
and marks the selected row with aria-current.

Opening the Streams tab now selects the first stream when the URL has no
streamId, so the first viewport shows stream data instead of an empty
placeholder.
@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 287911e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
@workflow/web-shared Minor
@workflow/web Minor
@workflow/cli Patch
@workflow/nitro Patch
workflow Patch
@workflow/world-testing Patch
@workflow/nuxt Patch
@workflow/core Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/vitest Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Jul 29, 2026 6:13pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment Jul 29, 2026 6:13pm
example-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-astro-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-express-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-fastify-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-hono-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-nestjs-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-nitro-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-nuxt-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-sveltekit-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-tanstack-start-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workbench-vite-workflow Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workflow-docs Ready Ready Preview, Comment, Open in v0 Jul 29, 2026 6:13pm
workflow-swc-playground Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workflow-tarballs Ready Ready Preview, Comment Jul 29, 2026 6:13pm
workflow-web Ready Ready Preview, Comment Jul 29, 2026 6:13pm

The trace sidebar and events list offer JSON copying via CopyButton /
CopyableDataBlock, but the Streams view never grew the same affordance.
Each chunk row in the ledger now reveals a copy action on hover, and the
Text view's non-text JSON blocks carry a copy button in their header,
both reusing the existing CopyButton primitive.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ze as label

The streams sidebar rendered the decoded label at 14px but the stream ID
at 11px; both now render at 14px. The ID uses the trace viewer's
MiddleTruncate (selecting truncated text copies the full ID) with a
hover-revealed CopyButton that copies the untruncated ID, and the viewer
header ID gets the same treatment. CopyButton and MiddleTruncate are now
exported from @workflow/web-shared. Sidebar rows move from <button> to
div[role=option][tabIndex] so the nested copy button stays valid HTML.

Co-authored-by: Cursor <cursoragent@cursor.com>
mitul-s and others added 6 commits July 28, 2026 17:11
The label + stream ID + copy action duplicated what the sidebar already
shows for the active stream. The header bar now keeps only the live
indicator, chunk count, and view toggle, right-aligned.

Co-authored-by: Cursor <cursoragent@cursor.com>
… chrome

The sidebar header reads simply 'Streams' and the viewer header keeps
only the live indicator and view toggle.

Co-authored-by: Cursor <cursoragent@cursor.com>
The viewer content now runs edge to edge; the live indicator and the
chunks/text view toggle float as an opaque cluster at the top-right,
following the same overlay pattern as the jump-to-latest action.

Co-authored-by: Cursor <cursoragent@cursor.com>
Reverts the floating-control experiment: the live indicator and view
toggle are back in the h-10 hairline header bar, which reads better
anchored than overlaid on the content.

Co-authored-by: Cursor <cursoragent@cursor.com>
…grid

The sidebar moves from 256px to 340px, the trace event list pane's
default width. Header bars, sidebar rows, and the viewer content now use
24px (px-6) horizontal padding so the sidebar header aligns with the
tabs above and the view toggle's right edge aligns with the run card's
actions.

Co-authored-by: Cursor <cursoragent@cursor.com>
The numbered gutter read as noise on the ledger; rows are now content
only, and non-text JSON blocks in the Text view are labeled without
their index.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants