Repository navigation
feat(web): add workspace panes and transitions - #28845
maria-rcks wants to merge 400 commits into
Conversation
|
Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting). This review would cost an estimated $35.80, which exceeds your per-review limit of $15.00. The top 3 files driving up this estimate:
Tip To get this pull request reviewed, you can:
|
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This introduces workspace panes and transitions, including changing the default panel animation duration from 0 to 150 ms. That product-default change and a new lint-suppression directive require human review. Needs human approval because:
Review your spending limits in Billing settings, or comment |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Other scenariosNo All 64 scenario measurements
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 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.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
f6f00d4 to
b653b87
Compare
b653b87 to
f0dd9b6
Compare
f0dd9b6 to
ba88740
Compare
ba88740 to
91b0851
Compare
91b0851 to
814c2e3
Compare
Checks visible timeline lists a second after a turn ends, the fold collapses, the thread is shown or the row count changes, confirms the gap a few seconds later, keeps the last 20 reports in localStorage and shows one toast per thread with a copy action. Exposes window.t3dev.gapReports, copyGapReports and checkGapsNow. Remove once the gap's cause is fixed.
A pull request open as a tab beside a chat answered only the copy-number shortcut, so Cmd+Shift+C did nothing there. The pull request detail now answers copy link while its pane is focused, through the same copy target and confirmation as the thread and the Pull requests page.
… them up with rows
Each tab's header rendered its own tab strip, so switching tabs swapped the strip out from under anything drawn in it. The strip is now one node per pane that the shown header holds; each header portals its tabs into its own layer, which stays mounted while the header is hidden and moves into the strip when it shows. The strip carries the joined tab's shape, placed under the active tab once per tab change and hidden until the connected pane tabs draw it. Looks unchanged.
From md up, a pane's top is a bar in the chrome's color. The focused pane's active tab is a piece of the pane rising into it, joined by concave ears, with one lit rim from its top round the ears and 36px out along the pane's edge, where it fades. An unfocused pane's active tab is a soft pill. Switching tabs slides the shape to the new tab over the panel animation duration with ease-out, transform only, and the labels fade between tiers on the same clock; focus moving between panes cross-fades the shape and the pill. Reduced motion and a duration of 0 turn both off. Light, black chrome keeps today's notch: its paint is scoped to .black-chrome and the modal pane, so it can be deleted on its own.
On the connected bar the joined tab names its kind (Diff, Files) and its breadcrumb and scope controls follow it on the bar as plain controls, so a wide breadcrumb no longer stretches the joined tab out of the strip. The breadcrumb gives way before the tabs when the pane is narrow. Black chrome and phones keep it inside the tab.
…when it lands The shape waited for the switch's commit and the incoming chat's layout, about 120 ms, while the labels changed at once. It now starts sliding on the press, measured from the tabs as they are, on its own compositor layers, so it keeps moving while the switch renders; a press that does not end in that tab showing brings it back. Labels read as active only under the landed shape. Every title gets the active one's room, so activating a tab moves no other tab. Where tabs are scrolled out, the strip fades at that edge as scroll areas do.
… half-width pane On the bar the breadcrumb shares the row with the pane's tabs, so the diff treats it as crowded: the head ref folds away below 36rem and the view controls fold into their menu, leaving the scope and the base in full.
The text field mic becomes the composer's bars and x where it sits, the live transcript streams into the field itself, and errors take the same slot, so no row is added and the buttons beside it stay put.
…emselves on hover Main's details-panel test drops the timeline registrar the canvas context no longer carries.
… redesign's default
The details button took the joined tab's 5px shift twice, once through the controls' top and once through their translate, so it sat 5px below the tabs in a single pane. It now takes only the translate, as it already did in split panes.
The suggestion and the composer placeholder now share the editor's text box, line height and wrapping, so Tab no longer nudges the words or resizes the composer. The Tab hint can't add a line and hides when it doesn't fit. The sidebar rename field keeps the title's line height.
… button and the timeline steady The sidebar slide moved the whole pane as one block from its final layout, so everything anchored to the right edge or centered took a detour: the details card swung 248px, the details button was clipped out of view while opening, and the timeline and composer jumped 213px before sliding back. Elements marked data-sidebar-slide-track now go straight from where they were to where they land, the slide waits for the chat lanes' resize observers before measuring, and while opening the pane clips by its shape so what stays at its right edge stays visible.
…imer A new worktree's checkout and setup script now show as ordinary work rows under "Working for", which counts from send through setup into the agent's work. When setup ends the stages fold into one "Set up worktree" row that opens on click. A failed or cancelled setup keeps its stage rows above the run's own outcome. Runs that prepared a worktree carry that fact on their summary, so the final "Worked for" counts from send too.
…otion Moves the track edge, the wait for resize observers and the clip lifting out of sidebar.tsx into motion/slideTrack.ts, unchanged.
Opening the diff, files or terminal panel, splitting or closing a pane, and toggling the sidebar beside split panes now move every pane edge, the details button, the tab bar's end corner, the timeline and the composer straight from where they were to where they land, together. Before, the pane making room resized on the first frame (timeline and details button jumped up to 532px) while the new pane slid into an empty gap for 326ms on a spring; beside split panes the sidebar slide moved the edge between them 136px the wrong way and back. Pane motion now uses the sidebar slide's ease-out for the Panel animations duration, snapshots tracked elements before React commits a new layout, and slides them from there once the chat lanes re-measure, keeping lanes on their pane's steady side. A sidebar toggle hands split panes to pane motion with a snapshot taken before its own commit.
…nline The reason sits in full above the field, the link is its host as a text link with the full address in a tooltip below it, the input drops the repeated label, and Save and Decline wrap together.
Part 6 of 6 of the T3 Code redesign. Chats, files, terminals and the browser open as panes in a workspace instead of fixed side panels.
The niri parts are behind Settings > Labs > Scrolling workspaces, off by default: the sideways scrolling strip and swipes, extra workspaces and the overview, and the layout tour and hints. With it off, panes shrink to fit; splits, tabs, side panes and per-project layout templates stay on for everyone. cmd+N and cmd+shift+O open main's project picker when there are several projects, and new threads replace the focused tab instead of opening a new one.
Needs approval: Theo for
vite.config.ts(lint ceilings only); Theo or Julius forpackages/contracts(ipc, keybindings, server, settings, including the newscrollingWorkspacesEnabledclient setting, which decodes to false).Stack
Do not merge: this stack still needs review. Each PR targets the one below it.
1-primitives-shell2-composer-timeline3-panels-pages4-settings-setup5-voice6-workspace-panes(this PR)Evidence
Captured against base
5ba6597504b681819ff657e5e0808c54b37edb42and headf6f00d4f4fe175e66f5d7fc6018ace6a1c841ca3, 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.
Browser: the same example.com page remains usable beside the chat and terminal, with the file and browser represented as workspace tabs.
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.
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.
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.
Usage adopts the floating settings shell. Both refs show the same real provider error, with matching selections, in dark mode.
Usage, matching light-mode pair.
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.
Findings and limits:
Codex could not read usage (JSON-RPC -32600). No usage data was fabricated.Verification
Every layer, rebased on main 9469095, 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