Skip to content

Fix comment input losing focus inside host-app modals (focus trap)#46

Open
sacrezm wants to merge 1 commit into
breschio:mainfrom
sacrezm:fix/comment-input-focus-trap
Open

Fix comment input losing focus inside host-app modals (focus trap)#46
sacrezm wants to merge 1 commit into
breschio:mainfrom
sacrezm:fix/comment-input-focus-trap

Conversation

@sacrezm

@sacrezm sacrezm commented Jun 19, 2026

Copy link
Copy Markdown

Problem

When you annotate an element that lives inside a host-app modal, the Drawbridge comment box appears but won't accept any text — you can't type the note.

Cause

Many apps render modals with a focus trap (e.g. Radix Dialog / @radix-ui/react-focus-scope, focus-lock). On every focusin that leaves the dialog subtree, the trap reclaims focus. Drawbridge injects its comment <textarea> (.float-comment-input) at <body> level in the light DOM, so from the modal's perspective the textarea is "outside" the dialog — the trap steals focus back the instant you click it, and typing is impossible.

Fix

Register a capture-phase focusin/focusout guard once at content-script load that calls stopImmediatePropagation() for focus events whose target is inside a Drawbridge node ([id^="moat-"],[class*="moat"],[class*="float-comment"]).

Capture phase runs before the app's bubble-phase focusin handler, so the trap never sees focus leave the dialog and the textarea keeps focus. Only Drawbridge-originated focus events are stopped, so the host app's own focus behavior is untouched, and click/submit handlers (different event types) are unaffected.

Test plan

  • Open an app that renders a modal with a focus trap (e.g. a Radix Dialog).
  • Open the modal, press C, click an element inside it, and type in the comment box.
  • Before: the box can't be typed into. After: it accepts text normally.
  • Annotating elements outside modals, and the app's own modal focus behavior, are unchanged.

Host-app modals with a focus trap (Radix Dialog / focus-lock) reclaim focus
whenever it leaves their subtree. Drawbridge injects its comment <textarea>
at <body> level (light DOM), so the trap steals focus the instant you click
the comment box and you can't type a note.

Add a capture-phase focusin/focusout guard that stops propagation for focus
events originating inside Drawbridge nodes
([id^="moat-"],[class*="moat"],[class*="float-comment"]). Capture runs
before the app's bubble-phase handler, so the trap never sees focus leave;
only Drawbridge-originated focus events are stopped, leaving the app's own
focus behavior untouched.
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