feat(web): add workspace panes and transitions#28845

open50+
maria/redesign/5-voice
maria/redesign/6-workspace-panes
opened4d agobyMmaria
View on GitHubTwo-way sync enabledPR last imported just now

Part 6 of 6 of the T3 Code redesign. Chats, files, terminals and the browser open as panes in a horizontally scrolling workspace instead of fixed side panels.

  • workspace panes with tab strips: reorder by drag, overflow scrolling that reveals the active tab, restoring closed tabs, and terminal panes in tab drop targets.
  • layout hints and a guided tour introduce the workspace and stay inside the viewport on mobile.
  • ⌥⌘ + scroll moves between columns. Pane backgrounds paint without a retained compositor layer, and hints follow compositor motion without a continuous repaint.
  • the usage page reuses the floating settings shell.

Needs approval: Theo for vite.config.ts (lint ceilings only); Theo or Julius for packages/contracts (ipc, keybindings, server, settings).

Stack

Do not merge: this stack still needs review. Each PR targets the one below it.

  1. #28839 1-primitives-shell
  2. #28840 2-composer-timeline
  3. #28841 3-panels-pages
  4. #28842 4-settings-setup
  5. #28844 5-voice
  6. #28845 6-workspace-panes (this PR)

Evidence

Captured against base 5ba6597504b681819ff657e5e0808c54b37edb42 and head f6f00d4f4fe175e66f5d7fc6018ace6a1c841ca3, using separate seeded worktrees and the same replay scenarios at 1280 × 720. Dark mode unless labeled light. No code, PR, or branch changes.

Chat, terminal, and the same server/package.json file: the fixed right panel becomes an independent workspace column.

before: chat and terminal beside package.json in the fixed right panel

after: chat and terminal beside package.json in a workspace column

Browser: the same example.com page remains usable beside the chat and terminal, with the file and browser represented as workspace tabs.

before: example.com in the fixed right panel beside chat and terminal

after: example.com in a workspace pane beside chat and terminal

Workspace tab strip: overflow scrolling and active filename reveal were exercised with package.json, README.md, tsconfig.json, vite.config.ts, and the browser. Measured 466 px of tab content in a 326 px viewport; selecting vite.config.ts revealed its filename. Native drag reordered vite.config.ts before README.md and before tsconfig.json in separate passes. The base has no workspace pane tab strip; its fixed panel baseline is shown above.

after: overflowing pane tab strip reveals the selected vite.config.ts filename

Restore a closed chat: Ctrl+Shift+T reopened Replay: todo-list with its existing conversation. Closing and restoring a browser also retained its URL and page. Chat-tab restore has no equivalent on the base.

after: restored Replay todo-list chat retains its conversation beside the browser

Layout introduction and guided tour are new on this layer. Opened Show me, advanced through all five steps, entered the overview lesson, and finished back in the workspace.

after: tabs side by side introduction with four layout diagrams

after: guided tour anchors its first step to the new tab control

Usage adopts the floating settings shell. Both refs show the same real provider error, with matching selections, in dark mode.

before: dark usage limits page reports the Codex JSON-RPC error

after: dark usage limits page in the floating settings shell reports the same error

Usage, matching light-mode pair.

before: light usage limits page with the Codex JSON-RPC error

after: light usage limits page in the floating settings shell with the same error

Nine-second recording: native tab drag, horizontal column scrolling, closing the chat, and restoring it. Reviewed the exported sequence, then played the uploaded video to completion and checked seeking.

after: native pane tab reorder, column scrolling, and closing and restoring a chat

Findings and limits:

  • The recording shows a brief empty pane during chat restoration around 5–6 seconds, before its conversation returns. This is observed app behavior, not a successful no-blank-frame result.
  • Usage retrieval is unverified: both refs report Codex could not read usage (JSON-RPC -32600). No usage data was fabricated.
  • This is a Linux web browser. Ctrl+Alt plus horizontal scroll moved the workspace strip from 223 px to 0 px. The macOS ⌥⌘ path, Electron desktop, native mobile, and three-finger gestures remain unverified.
  • Browser automation intermittently disconnected. Native drag succeeded after targeting the visible pane specifically; exploratory pointer-event checks were not used in the final recording.
  • No automated test suite or production-build checks were run for this evidence-only task.

Verification

Every layer, rebased on main 94690956fd, passes typecheck, knip, lint and format on Blacksmith on its own. At layer 6, the web suite passes (unit and browser). The desktop suite fails one libsecret test, which fails the same way on main. GitHub CI runs the full suite on every layer.

Done with Claude Code (Opus 5.5) and Codex (gpt-6.1-sol high) children in T3 Code.

🤖 Generated with Claude Code

Checks

4 successful · 6 skipped · 1 neutral
All checks passed
83c1f4b
Synced from GitHub

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $36.69, which exceeds your per-review limit of $15.00.

The top 3 files driving up this estimate:

FileDiff SizeEstimate
apps/web/src/layout/SurfaceHost.tsx80.38KB$3.15
apps/web/src/layout/layoutModel.ts66.55KB$2.61
apps/web/src/layout/Overview.tsx54.69KB$2.14

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

Synced from GitHub

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The workspace-pane changes also switch the panel-animation default from 0 ms to 150 ms. Human review is required to confirm this change to the default user experience.

Needs human approval because:

  • Per-review cost limit exceeded (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings, or comment @macroscope-app review this PR to bypass the limit and review now. You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire—5.0 KiB—6.8 KiB✅
CodexThread snapshot wire—3.8 KiB—4.9 KiB✅
CodexLive turn WebSocket wire—1.2 KiB—2.0 KiB✅
CodexLive turn WebSocket decoded—21.5 KiB—24.4 KiB✅
CodexLive turn messages—1—8✅
ClaudeTotal thread wire—5.0 KiB—6.8 KiB✅
ClaudeThread snapshot wire—3.8 KiB—4.9 KiB✅
ClaudeLive turn WebSocket wire—1.2 KiB—2.0 KiB✅
ClaudeLive turn WebSocket decoded—21.9 KiB—24.4 KiB✅
ClaudeLive turn messages—1—8✅

Baseline: unavailable · PR result: 1c1f0cf · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Review in Change Stack →

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Synced from GitHub

Note

Written by claude-opus-5-5 (Claude Code), reviewed by gpt-6.1-sol (Hermes), on behalf of Kevin

Independent Linux Electron check at 0d93d26 (Electron 44.10.1 / Chrome 152, unpackaged production build on a headless X server).

Ctrl+Alt + horizontal scroll does not move the workspace strip when the pointer is over the browser's guest page. The same gesture over the chat pane moves the strip in either direction.

Pointer locationThis PR
Chat paneStrip moves sideways
Browser guest (<webview>)No strip movement

Steps: open an overflowing three-column workspace containing a browser and a chat. Hold Ctrl+Alt and send horizontal wheel input over each pane, then reverse direction. The original check used X11 buttons 6/7 and a CDP wheel cross-check.

The capture listener in SurfaceHost.tsx is on the host scroller; guest-page wheel events do not propagate there. The desktop preview manager forwards key chords, but has no corresponding wheel forwarding path. This limits the new scroll gesture on Electron, rather than contradicting the Linux web-browser result in the PR.

Not checked: macOS ⌥⌘, Windows, packaged build, physical trackpad, native mobile.

Synced from GitHub

@t3dotgg @maria-rcks @juliusmarminge

Thank you for the work on this redesign. Much of it is a real improvement, and we appreciate the care that has gone into it.

As a user, however, I want to respectfully object to the new workspace layout: the separate rounded panes with folder-shaped notches, the gutters between them, and the grid background shown in these captures. To us, the disconnected panes look busy and unfinished.

We really like the flat design the app has today. The sidebar, the chat and the side panel sit edge to edge, divided by clean, sharp lines that run straight from the top of the window to the bottom. That flat, continuous layout is a big part of why the app feels calm and focused to work in, and it is the main thing we would not want to lose.

Could you please keep the current flat layout available as an option? A setting that preserves it would let those of us who prefer it keep working without switching to the new panes, while everyone else adopts the new style. We are glad to use the rest of the redesign; we would simply like to keep this layout.

Thank you for considering it, and for respecting the users who prefer the flat design.

Added 50 commits

  • fix(web): follow pane sizing while the terminal hint is visible2f5beb2
  • fix(web): track hint anchors through compositor motion33c7868
  • fix(web): use the design pane gutter between workspace columns4461b6b
  • fix(web): settle layout hints after pane transforms finish83f5a64
  • fix(web): reveal pane tabs when their breadcrumbs mount8f85376
  • fix(web): match pane tabs and held layout sheet to the designa07dda6
  • feat(web): introduce workspace tabs with a guided toura4bb82c
  • refactor(web): let the geometry tracker own hint movement listenersbb88407
  • fix(web): yield reopen shortcuts to modal dialogsf5b4ddf
  • fix(web): reuse floating settings shell for usage0298ba1
  • fix(web): constrain tour cards to their available width0aad0a1
  • fix(web): reserve mobile settings header actions in search1ea4b30
  • fix(web): sideways swipes over a terminal scroll the pane strip (#29054)2c8c07a
  • fix(web): closing a pane no longer blacks out the panes beside it (#29078)433556d
  • fix(web): Lineage shows short model names (#29138)561831b
  • fix(web): keybinding settings show only this platform's shortcuts (#29174)772fb3f
  • fix(layout): reuse focused launchers when opening content82adece
  • fix(web): keep lineage model metadata on separate linesb8f2405
  • fix(web): keep layout introduction actions reachable on mobilec0cb60d
  • fix(web): project picker rows show the icon of the folder they open (#29177)cbbfd35
  • fix(layout): reserve sidebar toggle space in surface headersd0be003
  • fix(web): pane corners keep the chrome grain under their curve (#29547)db29a04
  • fix(web): align settings shell and illustrate layout onboardinge537904
  • fix(layout): cover timeline content beneath pane headersf790676
  • fix(web): keep layout tour coaches inside the viewportfe2d263
  • fix(web): linked pull requests scroll up beside the pane tab notch (#29942)033bb5f
  • fix(web): keep pane tab labels to one resource title0c4866b
  • fix(web): pane tabs keep their icon and PR state when you switch tabs (#29080)0e7d326
  • fix(web): restore machine overview in environment settings126e393
  • fix(web): top-right notices sit below the pane notch, not inside it (#29983)1453261
  • fix(web): closing a subagent's tab goes back to its parent thread (#29608)1bcc847
  • refactor(web): remove the empty pane header actions wrapper28d74f1
  • fix(web): Pull requests is always a layout tab, so "+" keeps it open (#29968)33c1b83
  • fix(web): side pane tab bars match the pane below them (#29064)4e6f234
  • fix(web): closing a middle pane no longer blanks the panes beside it (#30002)50475e6
  • fix(web): the pull requests list scrolls under its header in one surface color (#29940)5d23df7
  • fix(web): match settings shell and pages to the design canvasa4fe56a
  • fix: retain layout compatibility checks after rebaseab73045
  • fix(web): sideways swipes scroll the pane strip over every pane (#29883)ca41ce1
  • fix(web): match project, archive and task settings to the design canvase3915ec
  • fix(web): drop the header Agents menu; Lineage covers it (#29568)eb1bb97
  • fix(web): the composer floats over the chat instead of sitting in a solid band (#30464)10b1de7
  • fix(web): the overview's new-workspace slots get the selection ring and glide like any workspace (#30584)2ba539f
  • fix(web): match thread details cards to the design canvas366751e
  • fix(web): the workspace hint sits at the same height on every pane (#30578)5c85c09
  • fix(web): thread details hide empty Servers and Automations cards (#30559)621f6af
  • fix(web): restore symbols the workspace panes used from main's rebased helpers83c1f4b
  • fix(chat): match the secret request card to the design canvas9c58a9c
  • fix(web): show context usage and its breakdown in thread detailse23de80
  • fix(web): align thread details summaries and usage rows with the designe374b13