[select][popover] Fix nested Select requiring extra outside clicks to dismiss parent#4820
Merged
atomiks merged 7 commits intoMay 14, 2026
Conversation
commit: |
Bundle size
PerformanceTotal duration: 1,159.02 ms -271.55 ms(-19.0%) | Renders: 50 (+0) | Paint: 1,771.61 ms -420.93 ms(-19.2%)
…and 1 more (+6 within noise) — details Check out the code infra dashboard for more information about this PR. |
✅ Deploy Preview for base-ui ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
4479439 to
eee9152
Compare
5496d98 to
0da72f1
Compare
Adds a minimal demo under popover/demos/nested-select-dismiss/ that reproduces a dismissal bug: a Popover containing a Select requires two outside clicks to dismiss instead of one. The Select dropdown does not need to be opened — its mere presence inside the Popup is enough. Not for upstream — drafted to validate the repro locally before filing an issue.
… dismiss parent
When a Select is rendered inside a Popover, dismissing the Popover via
outside click requires extra clicks instead of one. Two independent
issues contribute:
1. Select hardcodes `bubbles: false` in its `useDismiss` config,
which prevents the parent Popover's dismiss from firing while the
Select is open. Changed to `bubbles: !modal` so non-modal Selects
(the correct API for nesting inside another popup) allow the parent
to dismiss.
2. `handlePressEndCapture` in `useDismiss` falsely detects a
drag-from-inside-to-outside when the user clicks a nested popup
trigger that opens on mousedown (Select uses
`useClick({ event: 'mousedown' })`). The pointerup lands on the
nested popup's portal, which is outside the parent's DOM and not a
registered FloatingTree child. Added a guard that checks whether
the pointerup target is inside any open popup via
`[data-open]` / `[data-popup-open]` before triggering drag-out
suppression.
a166e40 to
efde047
Compare
Contributor
|
Coudn't get an automated failing test for:
But I manually verified that it works now in browser, with regular dismiss and drag dismiss flows Before: https://stackblitz.com/edit/emel6xue |
efde047 to
b1c20b3
Compare
atomiks
approved these changes
May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes nested
Select/Popoverdismissal paths where a parent Popover could require extra outside presses after Select interactions.The final fix is intentionally small:
Select.Rootnow usesuseDismiss(floatingContext)defaults instead of hardcodingbubbles: false. This keeps Escape isolated while allowing outside-press dismissal to cascade like other popup components.useDismissclears leftover drag-out suppression when a new press begins outside the floating element and its trigger, so stale suppression from a previous Select interaction cannot consume the next real outside click.Details
Popoveruses intentional mouse outside-press handling. In nested popup flows, an earlier interaction can leavesuppressNextOutsideClickRefset even though the next press is a fresh outside dismissal attempt. The guard clears that stale suppression on the new outsidepointerdown/mousedown; it does not clear suppression for the eventualclick, so legitimate inside-to-outside drag suppression is preserved.Removing Select's explicit
bubbles: falserelies onnormalizeProp(undefined)defaults:escapeKeyremains non-bubbling andoutsidePresscan bubble.Tests
Added Chromium coverage for Select inside Popover dismissal: