Skip to content

fix: preserve desktop composer focus across sends and navigation - #413

Merged
lodystage[bot] merged 3 commits into
mainfrom
fix/lody-pr-143-bug
Sep 5, 2026
Merged

fix: preserve desktop composer focus across sends and navigation#413
lodystage[bot] merged 3 commits into
mainfrom
fix/lody-pr-143-bug

Conversation

@lodystage

@lodystage lodystage Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Related issue

Refs #131

Follow-up to #143.

Problem / pressure

Desktop message submission still lost focus because clearing the real mention composer remounted its textarea, invalidating the previous DOM equality guard. Starting a conversation from chat landing also had no focus handoff to the newly mounted session composer. Mobile rejection recovery could reopen the keyboard, and the landing mount guard missed wide native tablets.

Summary

Keep the textarea mounted on empty transitions and reset mention data/menu/hydration separately. One scoped submission token owns lifetime identity and synchronous submission exclusion; explicit completion state restores desktop focus after React commits. Outside focus/pointer interaction and window blur relinquish ownership. Session changes/unmount retire submissions; late acceptance clears only an unchanged captured draft.

Desktop session creation carries a one-shot focus request in navigation state. Session detail passes the claim to its visible target composer, which consumes it when the input actually mounts, including delayed preparation. Consumption clears the history-state request so remounts and Back do not replay it; entry identity rejects stale claims.

Narrow mobile layouts and native shells, including wide iPads, never auto-focus on landing entry, session creation, or submission completion, whether accepted or rejected. Mobile submission dismisses the keyboard without installing desktop focus listeners. Explicit user focus actions remain available.

Ablation evidence

Individual deletions identified redundant active/finished flags, native focus eligibility checks, the keyboard/button source argument, imperative DOM clearing, and the counter that mirrored draft identity. Remove #143's parallel focus refs/effect and consolidate its repeated session-switch fixture into real-composer parameterized coverage.

The active-element fallback required a stronger replacement: removing it alone failed a stopped-propagation case; capture-phase focus observation covered that behavior and allowed the fallback's removal. Negative controls independently removed the post-commit handoff, lifetime identity, focus/pointer/window listeners, hydration reset, menu ownership, and submission lock; each caused observable regression failures and was reverted.

Test plan

  • Full pnpm check and formatting passed; unrelated formatter changes were excluded.
  • 57 focused component tests passed: 31 submission, 8 draft restoration, 10 mention activation, 3 composer focus, and 5 mixed mention restoration.
  • 9 Chromium tests passed: deferred Enter/button success/failure, continued typing, relinquished focus with/without stopped propagation, plus landing navigation and Back on desktop, narrow browser, and wide native-shell simulation.
  • Browser command: VITE_PREVIEW_PUBLIC_BASE_DOMAIN=preview.example.test pnpm --dir packages/components exec playwright test tests/e2e/composer-submission-focus.spec.ts --workers=1.
  • Navigation tests use the real router, landing view, composer, and shared session-creation navigation contract, with explicit preparation signals and synthetic drafts. Mobile keyboard behavior is simulated; no physical iOS/Android run was performed.

Context handoff

Instructions for reviewing agents

  • Review focus: Verify the visible composer owns the navigation claim, scope retirement preserves newer drafts, and clearing mentions preserves textarea identity.
  • Decisions to challenge: One-shot history state carries navigation intent; capture-phase observation owns desktop focus relinquishment; mobile has no completion auto-focus.
  • Plausible failures / evidence gaps: Native mobile keyboards lack device validation; Storybook exercises routing and real input views without the full authenticated session backend.

Authoring context

  • User goal / directives: Fix fix(desktop): restore input focus after sending message #143's remaining focus regressions, including landing navigation, remove redundant code through ablation, and exclude mobile auto-focus.
  • Constraints / non-goals: Preserve acceptance semantics and public platform boundaries; no daemon or cloud protocol changes.
  • Risk-bearing decisions: Late acceptance clears only the unchanged submitting draft; navigation focus is consumed once and completion focus is desktop-only.
  • Destructive or irreversible behavior: No migration or persistent schema change; draft clearing remains conditional on accepted submission.
  • Deliberately not done or tested: No physical iOS/Android run; native-shell and narrow-browser behavior use deterministic components and Chromium.
  • Unknowns / confidence: Real-component and browser regressions plus full repository checks support the fix; native keyboard timing remains unverified.

Consolidate submission lifetime and focus ownership after independent ablation and negative-control validation. Remove repeated PR 143 fixtures while preserving session-switch coverage.

Model: gpt-6
Carry a one-shot navigation focus request to the mounted session composer. Exclude narrow mobile layouts and native shells from entry and completion auto-focus, including rejected submissions.

Model: gpt-6
@lodystage lodystage Bot changed the title fix: preserve composer focus across submissions fix: preserve desktop composer focus across sends and navigation Sep 5, 2026
@lodystage
lodystage Bot merged commit 7dfc655 into main Sep 5, 2026
7 checks passed
@lodystage
lodystage Bot deleted the fix/lody-pr-143-bug branch September 5, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant