FocusScope skips a Tab stop after an exiting sibling scope unmounts
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- react, typescript
- Domain
- accessibility, frontend
Research direction
Start with the FocusScope cleanup condition and the other call sites of isAncestorScope; then run the forward- and reverse-Tab regression tests mentioned in the issue. Done means preserving an active descendant when an ancestor unmounts, with both regression tests passing and the existing whole-subtree focus restoration test unchanged.
Written by the indexing model from the issue text.
Description
🐛 Bug Report
When one overlay opens another before it finishes closing, unmounting the first overlay can break keyboard navigation in the second. One Tab skips a focusable element. On a fresh opening, Shift+Tab can move focus outside the second overlay even though its FocusScope has contain enabled.
The two scopes are siblings under an outer FocusScope in the React component tree. The second scope stays mounted, and focus is already inside it when the first scope unmounts.
🤔 Expected Behavior?
Removing the closing overlay should not change keyboard navigation in the overlay that remains open. Tab should move to the next focusable element, and Shift+Tab from the first element should wrap to the last. Focus should stay within the containing scope.
😯 Current Behavior
After the closing overlay unmounts, the first Tab skips the next button. Testing Shift+Tab instead on a fresh opening moves focus to a button outside the remaining overlay.
💁 Possible Solution
Change FocusScope cleanup so that it resets activeScope only when the scope being removed is itself active. If the active scope is a descendant that remains mounted, preserve it while removing its ancestor and reparenting it.
In the cleanup condition, this means replacing scopeRef === activeScope || isAncestorScope(scopeRef, activeScope) with scopeRef === activeScope. The isAncestorScope helper remains in its other call sites.
The added forward and reverse Tab regression tests fail without this change and pass with it. The existing whole-subtree focus restoration test also passes unchanged.
🔦 Context
Selecting a menu item opens another popover. The menu briefly remains mounted while the new popover opens. Once the menu unmounts, the first Tab in the new popover skips a button.
🖥️ Steps to Reproduce
https://codesandbox.io/p/sandbox/xfgnvy
- Open the standalone preview.
- Focus Open menu and press Space. Wait for focus to reach Choose date and time.
- Press Space again, then wait for the first overlay to fade out. Focus is now on September, the first enabled button in the second overlay.
- Press Tab once. Expected: 2026. Actual: Next month, skipping 2026.
- Reload and repeat steps 2–3. Press Shift+Tab instead. Expected: Next month (wrap to the last button). Actual: Open menu, outside the second overlay.
After the closing overlay unmounts, a single Tab skips a button in the overlay that remains open, even though its FocusScope still has contain enabled.
Version
react-aria@3.52.1
What browsers are you seeing the problem on?
Chrome
If other, please specify.
No response
What operating system are you using?
macOS 26.4.1, arm64
🧢 Your Company/Team
No response
🕷 Tracking Issue
N/A
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 50
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from adobe/react-spectrum
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
adobe/react-spectrum#10280 ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
adobe/react-spectrum#10068 · 8 comments · 2 reactions ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
adobe/react-spectrum#10037 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
adobe/react-spectrum#10026 ·
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
adobe/react-spectrum#10015 · 3 comments · 1 reaction ·
All issues in adobe/react-spectrum
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
danielmiessler/LifeOS#2218 ·