Skip to content

Keep chat composer focused after toolbar and mode interactions#49

Merged
juliusmarminge merged 3 commits intomainfrom
codething/d7b34bf2
Feb 16, 2026
Merged

Keep chat composer focused after toolbar and mode interactions#49
juliusmarminge merged 3 commits intomainfrom
codething/d7b34bf2

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Feb 15, 2026

Summary

  • keep the composer focused after branch selection and branch creation actions in BranchToolbar
  • add a scheduled composer focus helper in ChatView using requestAnimationFrame to restore focus after UI updates
  • trigger composer refocus after runtime mode changes, model selection, reasoning effort changes, and environment mode toggles
  • wire BranchToolbar to request composer focus via a new optional callback prop

Testing

  • Not run (tests not included in provided changes)
  • Manually verify changing runtime mode keeps the composer focused
  • Manually verify model and reasoning effort selection return focus to the composer
  • Manually verify switching env mode and selecting/creating branches returns focus to the composer

Open with Devin

Summary by CodeRabbit

  • New Features
    • Composer now automatically focuses after branch/worktree actions (select, checkout, create) for a smoother workflow.
    • Composer auto-focuses after model changes, reasoning-effort adjustments, and environment or runtime mode switches to reduce manual clicks.
    • Focus behavior is coordinated across UI controls so changes that affect context consistently return focus to the composer.

- Add a shared composer-focus scheduler in `ChatView`
- Refocus composer after runtime mode, model, effort, and env mode selections
- Let `BranchToolbar` request composer focus after branch/worktree actions
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 15, 2026

Walkthrough

Added an optional onComposerFocusRequest prop to BranchToolbar and threaded it through ChatView. ChatView introduces scheduleComposerFocus (deferred via requestAnimationFrame) and calls it after branch/worktree interactions, model/effort/env/runtime changes to refocus the composer.

Changes

Cohort / File(s) Summary
BranchToolbar focus integration
apps/web/src/components/BranchToolbar.tsx
Added optional onComposerFocusRequest?: () => void to BranchToolbarProps and invoke it after branch selection, worktree path changes, checkout mutations, and branch creation to request composer focus.
ChatView focus orchestration
apps/web/src/components/ChatView.tsx
Added internal scheduleComposerFocus (requestAnimationFrame). Wrapped handlers—model select, reasoning effort select, env mode change, and runtime mode change—to call scheduleComposerFocus. Replaced direct setEnvMode usage with onEnvModeChange passed to BranchToolbar and wired onComposerFocusRequest={scheduleComposerFocus}.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BranchToolbar
    participant ChatView
    participant Composer

    User->>BranchToolbar: select branch / create branch / change env
    BranchToolbar->>ChatView: call onEnvModeChange / onComposerFocusRequest
    ChatView->>ChatView: scheduleComposerFocus (requestAnimationFrame)
    ChatView-->>User: update UI / close menu
    ChatView->>Composer: focus composer (deferred)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (11 files):

⚔️ apps/server/src/wsServer.test.ts (content)
⚔️ apps/server/src/wsServer.ts (content)
⚔️ apps/web/src/components/BranchToolbar.tsx (content)
⚔️ apps/web/src/components/ChatView.tsx (content)
⚔️ apps/web/src/components/Sidebar.tsx (content)
⚔️ apps/web/src/components/ThreadTerminalDrawer.tsx (content)
⚔️ apps/web/src/lib/utils.ts (content)
⚔️ apps/web/src/terminal-links.ts (content)
⚔️ apps/web/src/wsNativeApi.ts (content)
⚔️ packages/contracts/src/index.ts (content)
⚔️ packages/contracts/src/ipc.ts (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: restoring composer focus after toolbar and mode interactions, which aligns with the primary objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codething/d7b34bf2
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch codething/d7b34bf2
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

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

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Feb 15, 2026

Keep the ChatView composer focused after BranchToolbar interactions, env mode toggles, model changes, and reasoning effort selections in ChatView.tsx and BranchToolbar.tsx

Add onComposerFocusRequest to BranchToolbar and invoke it after branch select/create; wire focus scheduling in ChatView via requestAnimationFrame after env mode, model, and reasoning effort changes.

📍Where to Start

Start with the scheduleComposerFocus helper and its call sites in ChatView.tsx, then review how onComposerFocusRequest is threaded and invoked in BranchToolbar.tsx.


Macroscope summarized c9fae23.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 15, 2026

Greptile Summary

This PR ensures the chat composer textarea retains focus after various toolbar and mode interactions (model selection, reasoning effort, runtime mode toggle, env mode switch, and branch selection/creation). It introduces a scheduleComposerFocus helper in ChatView that uses requestAnimationFrame to restore focus after UI updates, and passes it as a callback prop (onComposerFocusRequest) to BranchToolbar.

  • Added scheduleComposerFocus in ChatView wrapping the existing focusComposer in requestAnimationFrame
  • Wired focus restoration into onModelSelect, onEffortSelect, handleRuntimeModeChange, and a new onEnvModeChange callback
  • BranchToolbar accepts an optional onComposerFocusRequest prop, called after branch selection, branch creation, and env mode toggle actions
  • No functional issues found; the separation between onEnvModeChange (env mode toggle) and onComposerFocusRequest (branch actions) is clean with no double-focus risk

Confidence Score: 4/5

  • This PR is safe to merge — it only adds focus management callbacks with no changes to business logic or data flow.
  • The changes are narrowly scoped to UX focus management. The requestAnimationFrame-based approach is appropriate for deferring focus after React state updates. No business logic, data flow, or API interactions are modified. Minor style inconsistency (mixed useCallback usage) is not a functional concern.
  • No files require special attention.

Important Files Changed

Filename Overview
apps/web/src/components/ChatView.tsx Adds scheduleComposerFocus helper using requestAnimationFrame, and wires it into model selection, reasoning effort, runtime mode, and env mode changes. Clean separation of concerns with onEffortSelect, onEnvModeChange, and the onComposerFocusRequest prop.
apps/web/src/components/BranchToolbar.tsx Adds optional onComposerFocusRequest callback prop, invoked after branch selection and branch creation actions close the branch menu. Straightforward and correct integration.

Sequence Diagram

sequenceDiagram
    participant User
    participant ChatView
    participant BranchToolbar
    participant Composer as Textarea (Composer)

    Note over User,Composer: Model / Effort / Runtime Mode Change
    User->>ChatView: Clicks model/effort/runtime toggle
    ChatView->>ChatView: Update state (dispatch/setState)
    ChatView->>ChatView: scheduleComposerFocus()
    ChatView->>Composer: requestAnimationFrame → focus()

    Note over User,Composer: Env Mode Toggle
    User->>BranchToolbar: Clicks env mode button
    BranchToolbar->>ChatView: onEnvModeChange(mode)
    ChatView->>ChatView: setEnvMode + scheduleComposerFocus()
    ChatView->>Composer: requestAnimationFrame → focus()

    Note over User,Composer: Branch Selection / Creation
    User->>BranchToolbar: Selects or creates branch
    BranchToolbar->>BranchToolbar: Close menu, update thread
    BranchToolbar->>ChatView: onComposerFocusRequest()
    ChatView->>ChatView: scheduleComposerFocus()
    ChatView->>Composer: requestAnimationFrame → focus()
Loading

Last reviewed commit: c604768

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread apps/web/src/components/ChatView.tsx Outdated
- Remove unnecessary `useCallback` wrapping from `onEnvModeChange`
- Keep env mode update and composer refocus behavior unchanged
- Wrap model, effort, and env mode handlers in `useCallback`
- Stabilize callback identities while preserving composer focus behavior
@juliusmarminge juliusmarminge merged commit b7fb0b8 into main Feb 16, 2026
2 of 3 checks passed
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/web/src/components/ChatView.tsx (1)

815-826: Stabilize onModelSelect by depending on activeThreadId instead of activeThread.
Using the whole thread object will churn the callback whenever the thread updates; the id keeps memoization effective.

♻️ Suggested tweak
-  const onModelSelect = useCallback(
-    (model: ModelSlug) => {
-      if (!activeThread) return;
-      dispatch({
-        type: "SET_THREAD_MODEL",
-        threadId: activeThread.id,
-        model: resolveModelSlug(model),
-      });
-      scheduleComposerFocus();
-    },
-    [activeThread, dispatch, scheduleComposerFocus],
-  );
+  const onModelSelect = useCallback(
+    (model: ModelSlug) => {
+      if (!activeThreadId) return;
+      dispatch({
+        type: "SET_THREAD_MODEL",
+        threadId: activeThreadId,
+        model: resolveModelSlug(model),
+      });
+      scheduleComposerFocus();
+    },
+    [activeThreadId, dispatch, scheduleComposerFocus],
+  );

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.

1 participant