fix: Subagent list: focus falls to the body when the region unmounts on the way back to main - #8638
Conversation
🚀 Preview deployed
|
|
review-code: PASS @ 1302421 content:f0ad1036ac89 — merge-ready Text gate over the four changed files at this head. CI at the head is green: 45 runs, 41 success, 4 skipped, 28 of 40 repo-authored workflows produced a run. A routed Criteria
The rest of the sweep
DeviationsBoth disclosed entries check out against the diff, and nothing undisclosed was visible to this gate.
Verdict-written: 2026-09-08T21:48:20Z |
|
routed-elsewhere: review-ui @ 1302421 — Tuval surface; no admissible renderer until #7306 lands (founder ruling 2026-09-06). Text review PASS + builder hand-verification stand in. Tuval surface; no admissible renderer until #7306 lands (founder ruling 2026-09-06). Text review PASS at 1302421 (review-code) and the builder's hand-verification stand in: 27 files / 372 tests under apps/tuval/src/shell/chat green plus AgentChatInput's 25; focus destination asserted on document.activeElement for Escape and the back button; the founder ruled the Claude Code model on 2026-09-08. Sunset list entry 53 on #7306. |
Leaving a subagent view now puts DOM focus on the composer, every time.
Before this,
SubagentListasked for its own first line on the way back. When the only worker hadfinished, main had no rows, the whole region unmounted and there was no line to focus — DOM focus
fell to the document body, by Escape and by the back button alike.
The founder ruled the Claude Code model on #8470 (comment 5589657679): nothing auto-returns, and on
leaving, focus lands on the composer. So the destination moved out of the list and into the window.
SubagentListno longer requests focus for the way back;pickMainwas a one-line wrapper overonMainand is gone with it. The "more" row still names its own destination, unchanged.ChatWindow.showMainflags the leave and a layout effect places focus once the commit has landed.It runs after the render that re-enables the composer (The Tuval composer says nothing about where a prompt goes while a subagent view is open #8466's
disabled={viewing !== null}), sothe field takes the focus rather than refusing it while disabled.
AgentChatInputgained an optionalrefto its prompt field. The composer is the only control ahost can be asked to focus, so the ref is the textarea and not a handle.
Four cases in
subagent-navigator.unit.test.tsx: the last finished worker by Escape and by the backbutton (the region gone, composer focused and enabled), and the two-workers-remain path where the
navigator survives and focus still leaves it. The finished-worker setup asserts Q9 on the way — the
view stays open under the worker that finished, until the operator leaves.
Fixes #8470
Deviations
Did: rewrote two standing cases in
subagent-navigator.unit.test.tsxthat asserted focuslanded back on the list's first row. Why: those cases pinned the behaviour the founder's
ruling replaces; leaving them would have been a red on the ruled outcome.
Disposition: stated here.
SubagentList.tsxandChatWindow.tsx. Did: also added an optionalrefprop toAgentChatInputinpackages/design. Why: the field's id is auseIdvalue and the component exposed no handle,so the window had no typed way to reach the textarea; a class-name query from the consumer would
couple Tuval to a design-package internal. Renders nothing new and changes no default.
Disposition: stated here.