Skip to content

fix(select): stop selected highlight sliding from previous value on reopen - #22

Merged
mickadesign merged 1 commit into
mickadesign:mainfrom
fdarian:fix-select-reopen-highlight
Jul 27, 2026
Merged

mickadesign merged 1 commit into
mickadesign:mainfrom
fdarian:fix-select-reopen-highlight

Conversation

@fdarian

@fdarian fdarian commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

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.div animated top/left/width/height, but it only marks the checked row, which never changes within an open session. checkedIndex (its position) is resynced to value only inside the open-gated measure effect, and picking an item changes value at the same instant the popup closes, so that effect skips the update and checkedIndex keeps 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 moves checkedIndex to 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.moderate stays on its position, so an in-session value change (a controlled value updated while the popup is open) still springs. Also clear checkedIndex on close so the marker stays hidden until the new row is measured and never mounts at the stale previous row. Same change in registry/base/select.tsx and registry/radix/select.tsx. In the Radix flavor the reset keys off the visual open state (not the deferred radixOpen), matching the measure effect it complements.

Verification

npm run lint (0 errors) and npm run build both 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.

…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.
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

@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
mickadesign merged commit 5307707 into mickadesign:main Jul 27, 2026
1 check failed
mickadesign added a commit that referenced this pull request Jul 27, 2026
@mickadesign

mickadesign commented Jul 27, 2026 •

Copy link
Copy Markdown
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants