Repository navigation
fix(select): stop selected highlight sliding from previous value on reopen - #22
Merged
mickadesign merged 1 commit intoJul 27, 2026
Merged
Conversation
…eopen
The selected-background highlight marks the checked row. checkedIndex is only
re-synced to value while the popup is open, and picking an item changes value at
the same instant the popup closes, so on reopen the persisted marker springs
across from the previous row before the measure effect catches up.
Clear checkedIndex on close so the marker never mounts at the stale row, and
remount it per open (keyed on an open-generation counter) so initial={false}
snaps it to the checked row instead of springing across. An in-session value
change still springs, since the key only changes on open. Applied to both the
Base UI and Radix flavors.
|
@fdarian is attempting to deploy a commit to the mickatouillaud-gmailcom's projects Team on Vercel. A member of the Team first needs to authorize it. |
mickadesign
added a commit
that referenced
this pull request
Jul 27, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
Owner
|
Merged — thank you for the excellent work here! The root-cause analysis in the description was spot on and made this a joy to review. Both flavors verified clean (lint, tsc, build) and the registry payloads have been regenerated. |
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
After changing the Select's value, the first reopen of the dropdown animates the grey selected-background highlight in from the previously selected row instead of showing it on the current one. Every reopen after that is correct. Affects both the Base UI and Radix flavors.
Before (highlight slides in from the old value):
CleanShot.2026-07-24.at.18.06.24.mp4
After (highlight snaps to the checked row):
CleanShot.2026-07-24.at.18.06.52.mp4
Root cause
The selected-background
motion.divanimatedtop/left/width/height, but it only marks the checked row, which never changes within an open session.checkedIndex(its position) is resynced tovalueonly inside the open-gated measure effect, and picking an item changesvalueat the same instant the popup closes, so that effect skips the update andcheckedIndexkeeps pointing at the previous row. Base UI defers the popup unmount (and a quick reopen cancels it), so the element persists; on the next open the effect finally movescheckedIndexto the new value and framer-motion tweens the highlight across from the old row.initial={false}only suppresses the first-mount animation, not this animate-target change.Fix
Remount the marker on each open, keyed on an open-generation counter, so
initial={false}snaps it to the checked row on reopen instead of a persisted element springing across from the old row.spring.moderatestays on its position, so an in-session value change (a controlledvalueupdated while the popup is open) still springs. Also clearcheckedIndexon close so the marker stays hidden until the new row is measured and never mounts at the stale previous row. Same change inregistry/base/select.tsxandregistry/radix/select.tsx. In the Radix flavor the reset keys off the visualopenstate (not the deferredradixOpen), matching the measure effect it complements.Verification
npm run lint(0 errors) andnpm run buildboth pass. By hand: pick a new value, close, reopen; the highlight now appears on the checked row with no slide, on the first reopen and every one after. Change is isolated to the two Select files; the hover-background and focus-ring animations are untouched.Note on WebKit
This change is not sufficient on its own. In WebKit (Safari, and the WKWebView in a Tauri app) the highlight still slides on reopen: the element that slides is the hover pill rather than the selected marker, and the item rects it reads can be corrected after it has already mounted, which Framer Motion animates. The artifact is a race, so it also reproduces in Chromium depending on timing.
fdarian#1 stacks on this branch and fixes that at the source, in the shared proximity-hover hook. It also supersedes the per-open remount here. Merging this branch alone leaves the reopen slide in WebKit.