Skip to content

Fix focus trap stealing focus on render#737

Open
Luminous9 wants to merge 3 commits into
intuit:masterfrom
Luminous9:fix-focus-trap
Open

Fix focus trap stealing focus on render#737
Luminous9 wants to merge 3 commits into
intuit:masterfrom
Luminous9:fix-focus-trap

Conversation

@Luminous9

@Luminous9 Luminous9 commented Jul 21, 2026

Copy link
Copy Markdown

What Changed

  • Updated FocusLock to trap focus only when activated instead of after every render.
  • Added cleanup for pending focus timers.
  • Rechecked the active state and focused element before moving focus.
  • Added unit tests covering activation, rerenders, deactivation, and unmounting.

Why

FocusLock registers its focus-trap effect with no dependency array, so it re-runs on every render, and the focus correction is scheduled through an uncancelled setTimeout(..., 50). On each run, if focusInside(trap) is false, it calls moveFocusInside to pull focus back to the trap's first tabbable element.

The probelm is that focusInside checks document.activeElement at the moment the delayed callback fire, not static DOM containment. When the lock re-renders repeatedly (e.g. user keystrokes inside a nested overlay's input) the trap re-checks focus during transient windwos where document.activeElement isn't yet the intended element. It reads that as "focus escaped" and takes focus away, so typing a single character bounces focus out of the input field.

The fix gates the effect on activation transitions and stops state delayed moveFocusInside from firing during a transient blur.

@kelyvin kelyvin added the minor Increment the minor version when merged label Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Increment the minor version when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants