Repository navigation
feat(web): replace the Resources popover with a trigger, dock and inspector - #631
Merged
Merged
Conversation
danyaberezun
requested review from
Olga Lavrichenko (OLavrik),
Rustam Sadykov (SBOne-Kenobi) and
Rinat S (rsolmano)
as code owners
October 5, 2026 02:35
…row text the Inspect control
danyaberezun
force-pushed
the
redesign-resources-ui
branch
from
October 5, 2026 11:17
27d6056 to
0e0ebee
Compare
Olga Lavrichenko (OLavrik)
approved these changes
Oct 5, 2026
Rinat S (rsolmano)
approved these changes
Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Background commands and subagents that an agent starts are the work most likely to run while you type, and today they are the least visible: a header popover with three-line rows, a lowercase status word (
runningandqueuedlook identical at a glance), no elapsed time, no sense of what a row is doing, and separate modal dialogs for logs and transcripts that cover the chat. Nothing is visible while the popover is closed except a bare count, so "is the dev server still running?" means opening a popover and reading a word.A survey of how Claude Code, Codex, Cursor, Zed, T3 Code, Conductor, Warp, Amp, Antigravity, OpenCode, Kiro and others surface the same thing (COMPETITIVE-ANALYSIS.md, on the review-only
assets/resources-redesignref) converged on the same answer: an ambient live roster where you type, one detail view, one row grammar, and no roster rendered twice.Approach
The popover is replaced by three surfaces that share one row grammar — the direction the design review settled on ("G"):
—otherwise; the icon breathes while anything is live;aria-expandedtoggles the inspector.↑/↓,Esc) and the selected row's detail: bounded command output or the read-only subagent transcript. It replaces the popover, the command-log dialog and the Resources-origin transcript dialog.Decisions worth a reviewer's eye:
—, a stale snapshot disables Stop everywhere (dock summary says "reconnecting"), Stop means "requested", closing anything never stops work, an old host hides all three surfaces.chat/resourcesmodule still imports nothing from store/transport. Time arrives as anowprop (the shared 30 s clock) rather than widening that boundary.DialogPanelprimitive rendersDialog.Contentin place (no portal/overlay), soEsc, focus return to the trigger (composer fallback when an older host removes it) and the dialog role come from Radix, not hand-rolled handlers. Dock rows are real<li>s whose name is the Inspect button; inspector rows are listbox options — no nested interactive elements.Changes
apps/web/src/chat/resources/: newResourcesDock,ResourcesInspectorand a privateresourceRow.tsx(state collapse, sorting, elapsed formatting, the shared row);ResourcesButtonbreathes while live and carriesaria-expanded;CommandLogViewdrops its redundant status line;ResourcesContentdeleted. Public surface:ResourcesButton,ResourcesDock,ResourcesInspector,CommandLogView(spec-surface checked).components/ui/dialog.tsx:DialogPanel— in-place, non-modal content; caller positions it.chat/SubagentTranscriptDialog.tsx:SubagentTranscriptPaneextracted (polling + rows); the dialog wraps it, the inspector embeds it.chat/ChatView.tsx: oneinspectorstate (open + selected row, chat-scoped); trigger toggles it; dock mounts belowQueueStriponly while the inspector is closed; inspector mounts inside thechat-scrollregion;useCommandLogkeys off the selected command only; the command-logDialogand the Resources-origin transcript bookkeeping are removed;knownUnsupportedcloses the inspector and the Stop-all confirmation.chat/turns.tsx:TurnDivideraccepts an optionalstillRunningdeep link; ChatView supplies it for the chronologically latest divider while live resources exist ("N still running" chip → inspector).chat/resources/SPEC.mdrespecified (responsibility, boundary, row grammar, presentation of all three surfaces, verification obligations);chat/SPEC.mdChat Resources + transcript-pane paragraphs;components/ui/SPEC.md(DialogPanel);UI-TERMINOLOGY.md(Resources section, test ids);e2e/SPEC.mdwording.chat/resources/resources.test.tsxrewritten (boundary, vocabulary, trigger, dock, inspector, command log);e2e/chat-resources.spec.tsrewritten around the inspector (empty state + dock absence, composer click does not dismiss, focus return, phone width, reconnect/reload, old host, retirement with an embedded transcript);e2e/chat-resources.live.spec.tstranslated to the new ids (provider-backed — not run here).assets/resources-redesignref — the spec is the durable record of the decisions; the mockups are already drifting from the shipped rows.Not in this PR (follow-ups from the design review): merging
QueueStripinto the dock as one composer tray, Inspect on the Agent/background-command cards, a workspace-scoped inspector (needs a wire read), and the chat-tab / rail status vocabulary.packages/contracts+packages/server: an additive optionalSubagentResourceSummary.durationMs— pi-delegation's measured run time, exposed once a child is terminal — so settled subagent rows report a duration like completed commands do (from review).Screenshots
Same scenario (an injected
SessionResourcessnapshot: 2 live commands incl. one stopping, running + queued subagents, 3 finished) at 1440×900, dark theme. Before captured at the base commit, after on this branch's final tree.After — a subagent selected in the inspector (its transcript pane embedded):
Related issues
None.
Checklist
bun run lint,bun run typecheck,bun run testbun run e2e, orbun run e2e:fullwhen touching agent behavior)SPEC.md/ top-level specs updated to reflect any boundary, contract, or behavior changeTesting
On the final rebased tree (
origin/main= #628):bun run e2e -- --serial e2e/chat-resources.spec.ts e2e/chat-resources-wire.spec.ts→ 5 passedbun run e2e→ all 8 shards passed, 465 tests (run on the pre-rebase tree; the rebase pulled in feat(web): borderless labelled composer controls #628's composer styling only, so the resource specs above were re-run and the rest of the suite's inputs are unchanged)bun test(apps/web) → 1318 passcheck:deps,check:boundaries,check:seams,typography:check,colors:check,spacing:check,provider-glyphs:check,bun run lint,bun run typecheck) → all green, with one caveat:@thinkrail/desktop#typecheckcould not run locally — itselectrobun preparestep blocks on the build engine held by the running desktop dev app (0 CPU for 13 min).apps/desktopis untouched by this branch; the other 17 packages typecheck clean. CI will run it.bun run check:spec-surface→ OK (20 enrolled, 20 compared)e2e/chat-resources.live.spec.ts(provider-backed; translated to the new ids and cross-checked against the components' test ids)