[select] Release the forced popup mount and add keepMounted prop - #5343
Draft
atomiks wants to merge 6 commits into
Draft
[select] Release the forced popup mount and add keepMounted prop#5343atomiks wants to merge 6 commits into
keepMounted prop#5343atomiks wants to merge 6 commits into
Conversation
commit: |
Bundle size
PerformanceTotal duration: 1,136.01 ms +105.65 ms(+10.3%) | Renders: 78 (+0) | Paint: 1,783.86 ms +175.85 ms(+10.9%)
14 tests within noise — details Metric alarms
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. |
keepMounted prop
atomiks
force-pushed
the
claude/optimistic-payne-211dac
branch
3 times, most recently
from
July 27, 2026 00:22
f9f2a4f to
014692c
Compare
atomiks
force-pushed
the
claude/optimistic-payne-211dac
branch
from
July 27, 2026 05:23
014692c to
af66fec
Compare
atomiks
force-pushed
the
claude/optimistic-payne-211dac
branch
from
July 27, 2026 05:23
af66fec to
3d6ed91
Compare
atomiks
force-pushed
the
claude/optimistic-payne-211dac
branch
from
August 6, 2026 22:13
3d6ed91 to
611f3f6
Compare
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.
Closes #5184.
Problem
Select.PortalsetforceMounton trigger focus and never released it: after the first interaction the whole portal subtree — positioner, popup, and every item — stayed in the DOM for the lifetime of the page. The mount can't simply be dropped on close, because closed-trigger typeahead and autofill matching read labels, values, and disabled state from mounted items.Changes
forceMountbecomes a transient, focus-scoped mount instead of a permanent latch. Closed-trigger typeahead can only receive keystrokes while the trigger is focused, so the hidden items are kept mounted exactly then: armed on trigger focus (as before), released on trigger blur and after a close completes with focus elsewhere. Autofill mounts the items for a single microtask to match the value, then releases. No snapshot of item data is taken, so the React 18 index-guessing hazards of the earlier mirror approach don't apply.keepMountedtoSelect.Portal, the only popup-family portal missing it.selectedIndexandselectedItemTextRefon unmount. A stale index madeSelectItemTextre-adopt the ref on remount, misaligningalignItemWithTriggerafter option replacement.validationMode="onBlur").Behavior change
Removing the selected item from the list while the select is closed and unmounted reconciles the value the next time the items mount (any focus on the trigger remounts them), instead of immediately — there is no DOM to observe the removal against while unmounted.
The select-specific Motion handbook section is removed: Select now animates like every other popup, so the generic recipes (
AnimatePresenceunmounting, orkeepMountedwithactionsRefmanual unmounting) apply.Follow-ups
Combobox/Autocomplete's analogous sticky
forceMountedlatch is released the same way in a separate change.Pre-existing and unchanged by this PR:
useAnimationsFinished's close-complete scan can miss a JS-driven exit animation that registers a frame late (e.g. Motion animating offstate.openwithoutactionsRef), applyinghiddenmid-exit to a kept-mounted popup. The sticky mount onmasterhas the same scan and timing. The documentedactionsRefrecipe is unaffected because it disables the automatic scan.I have followed (at least) the PR section of the contributing guide.