Skip to content

fix(native-chat): focus the composer after a keyboard switch between chats - #29152

Merged
AmoabaKelvin merged 1 commit into
stablyai:mainfrom
AmoabaKelvin:fix-chat-switch-composer-focus
Oct 15, 2026
Merged

AmoabaKelvin merged 1 commit into
stablyai:mainfrom
AmoabaKelvin:fix-chat-switch-composer-focus

Conversation

@AmoabaKelvin

@AmoabaKelvin AmoabaKelvin commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​15 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​15
Prod 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​4 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​4

ELI5

With two chats open, switching between them with Ctrl+1 / Ctrl+2 often left the message box unfocused, so nothing you typed went anywhere until you clicked into it. Now the message box is ready every time.

What Changed

Before: a keyboard switch between two chat tabs usually left focus on the page body. Clicking a tab worked, because the click moved focus off the old chat first.

After: the chat you switch to gets its message box focused, however you got there.

Mechanism: when a chat is revealed, it focuses its composer unless some other text field already has focus. shouldPreserveEditableFocus decides what counts as a text field the user is editing. Right after a keyboard switch, the previous chat's composer is still document.activeElement, even though its pane is already inert and display: none. Chromium only moves focus to <body> a task later, after the reveal has already given up. The check now ignores a field inside a [hidden] or [inert] subtree, since nobody can be typing into it.

Why

The wrong answer came from this check, so the fix goes there and not into the chat hook. The two terminal callers get the corrected answer too, and they had no reason to protect a hidden field either. Adding an explicit focus call to every keyboard tab-switch path would also work, but it would leave the check giving the wrong answer to anything else that relies on it. [hidden], [inert] is the same selector the reveal hook already uses for focus that is about to drop.

Linked Issue

Fixes #28157

Visual Proof

N/A for screenshots: nothing on screen changes except where the caret ends up. In a hidden dev build with two Claude chats, I traced focusin/focusout/focus() over 30 alternating activateTabNumberShortcut switches (the handler behind Ctrl+digit). On main, 29 of 30 ended with focus on <body> and no focus() call. With this change, all 30 focused the new composer, and typed text went into the right chat with each draft kept.

Testing

  • I manually tested these changes locally (macOS, hidden dev build, as above; switching from a chat to a terminal by keyboard still focuses the terminal)
  • Automated tests added/updated: a reveal-focus test where the previous chat's composer is still focused inside a newly inert pane. It fails without the fix.

Review

Renderer-only. No wire, saved-state or platform-specific changes, so SSH, folder workspaces and mobile are unaffected.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

#28987 changes the same hook for new chats in split panes. That's a separate path and doesn't cover this bug. The two changes don't conflict.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…chats

The previous tab's hidden composer still held focus when the reveal hook ran,
and was treated as a live text field, so the new composer never got focus.

Fixes stablyai#28157
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e975c6fe-5d5d-4d03-8f8a-ecf90dd15781
📥 Commits

Reviewing files that changed from the base of the PR and between a3373af and 3addd1f.

📒 Files selected for processing: 2
  • src/renderer/src/components/native-chat/native-chat-composer-reveal-focus.test.tsx
  • src/renderer/src/components/terminal-pane/pane-helpers.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

shouldPreserveEditableFocus now returns false for elements inside a [hidden] or [inert] ancestor. A test verifies that revealing chat moves focus from a textarea in an inert pane to the chat composer.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 3addd

When switching panes, the revealed chat composer can receive focus even if focus remains in the now-inert pane. No material merge risk remains.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Issue #28157 requires keyboard switching between Chat UI tabs to focus the newly selected composer. The PR updates shouldPreserveEditableFocus to reject editable elements inside [hidden] or `[iner…
Out of Scope Changes check Passed The PR changes one shared focus predicate and adds one focused regression test. Both changes support the linked keyboard tab-switch focus behavior. No unrelated product, persistence, transport, or pla…
Title check Passed The title clearly and concisely identifies the primary fix: restoring composer focus after keyboard switching between chats.
Description check Passed The description is complete and aligned with the repository template. It explains the user impact, mechanism, rationale, linked issue, visual-proof exception, testing, scope, and checklist status.
  • Fix all pre-merge checks with AI
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AmoabaKelvin
AmoabaKelvin merged commit e8c7b32 into stablyai:main Oct 15, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Keyboard tab switch between Chat UI tabs often leaves the message box unfocused

1 participant