Repository navigation
fix(web): clicked workspace areas no longer show the focus ring after a stray key - #33525
Conversation
…e key press A workspace area focused by a mouse click starts matching :focus-visible once a lone key (a modifier delivered by a window switch) reaches the page, so it draws the area focus ring and counts as keyboard-reached on window return. Areas reached with F6 keep both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Chromium's :focus-visible turns on for an area the user clicked as soon as any bare key reaches the page, such as a modifier delivered on window activation. That drew the F6 ring around the clicked home or conversation area and blocked the composer refocus on window return. The workspace focus controller now marks an area when it focuses the area itself and :focus-visible matches at that moment. Focus moving to another element or a pointer press clears the mark; a window switch does not. The ring and shouldRefocusComposerOnWindowFocus read that mark instead of bare :focus-visible, and the area rule also suppresses the UA focus ring. Fixes #28166 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mark an area on focusin when focus arrives there from elsewhere and is keyboard-visible, instead of only when the controller focuses it, so focus a dialog returns to the area keeps its ring. Window activation refocuses the same element and is not an arrival, so a clicked area still never rings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Workspace focus rings and window-return focus now use an explicit keyboard-focus marker, avoiding stray rings after pointer interaction. The change is limited to transient UI focus behavior and preserves existing input and popup protections. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
kupiainen
left a comment
There was a problem hiding this comment.
fixes annoying "feature" that happens a lot to me.
**v0.1.8-nightly.20261109.4433** · 13 changes from 4 contributors - **Claude Fable 5.2.** Choose Claude Fable 5.2 from the model picker. - **Faster model discovery.** Opening the model picker checks for new models and surfaces the Claude Code update needed to use them. ### Plus 8 more bug fixes. <details> <summary>Full changelog</summary> ## What's Changed * fix(mobile): the thread feed re-wraps once when an iOS column resizes by @juliusmarminge in pingdotgg/t3code#33459 * fix(speech): match reference benchmarks to transcription hardware by @UtkarshUsername in pingdotgg/t3code#31956 * feat(models): add Claude Fable 5.2 by @t3dotgg in pingdotgg/t3code#33500 * fix(mobile): the chat inset resets after the keyboard closes while frozen by @juliusmarminge in pingdotgg/t3code#33501 * fix(mobile): a full swipe on a thread row finishes even if the pan is cancelled by @juliusmarminge in pingdotgg/t3code#33492 * fix(client): finishing a long background thread no longer freezes the app by @juliusmarminge in pingdotgg/t3code#33503 * feat(models): the model picker checks for new models when it opens by @t3dotgg in pingdotgg/t3code#33511 * fix(desktop): close focused DevTools with Cmd+W by @Yash-Singh1 in pingdotgg/t3code#33518 * chore(mobile): update react-native-pdf-jsi to 6.1.0 and link it on Android only by @juliusmarminge in pingdotgg/t3code#33504 * fix(mobile): the unfolded Duo sidebar no longer pops back in while resizing Files by @juliusmarminge in pingdotgg/t3code#33510 * fix(models): new models also surface the CLI update that supports them by @t3dotgg in pingdotgg/t3code#33515 * fix(web): clicked workspace areas no longer show the focus ring after a stray key by @t3dotgg in pingdotgg/t3code#33525 * chore(server): update Claude Agent SDK to 0.3.321 by @t3dotgg in pingdotgg/t3code#33530 **Full Changelog**: pingdotgg/t3code@v0.1.8-nightly.20261109.4429...v0.1.8-nightly.20261109.4433 </details> Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.1.8-nightly.20261109.4433
Problem
Click an empty part of the conversation or home area. Then press any bare key, such as Shift or Meta. A 2px focus ring appears around the whole area. A window switch can send that key for you (Hyprland focus-follows-mouse, a Super-key window switch), so the ring shows up with no keyboard navigation at all.
The cause is
[data-workspace-area]:focus-visible. Chromium turns:focus-visibleon for the element that already has focus when a key arrives. The same selector made the window-return check treat a clicked area as "reached from the keyboard", so the caret did not go back to the composer.Change
The workspace focus controller now marks an area with
data-workspace-keyboard-focusonly when keyboard focus arrives on it: F6, a focus request, or focus that returns from a dialog. A pointer press, focus moving elsewhere, and dispose clear the mark. Window activation refocuses the same element, so it does not count as an arrival.The ring in
index.cssandshouldRefocusComposerOnWindowFocusread the mark instead of:focus-visible.This replaces #28191 by @juliusmarminge, which was 1160 commits behind
mainand had a conflict. The five original commits are kept with their authorship. The one conflict was inChatView.logic.ts:mainrenamed the sidebar selector to[data-sidebar-row]:focus-visible, and this branch keeps that name.Scope and approval
Fixes #28166
Verification
Web app from
vp run dev, T3 Code browser panel, 1280x800. Steps: click the empty conversation area, then press Shift.main2da1b74)outline: solid 2pxoutline: noneF6 still shows the ring, and a click removes it again:
vp test run --project browser src/lib/workspaceFocus.browser.test.ts src/components/ChatView.logic.browser.test.ts(apps/web): 21 passed.vp run check:changed: format, lint, knip, typecheck, tests, and React compiler pass.Not checked:
Original work: Claude Opus 5.5 and GPT-6.1 Sol in T3 Code. Rebase, conflict fix, and verification: Claude Fable 5 in Claude Code.
🤖 Generated with Claude Code