fix(desktop): keep submenus pinned to their trigger during scroll
A portaled DropdownMenuSubContent keeps its Floating UI positioning on
the default "optimized" strategy: passive scroll listeners that only
reposition between events. While the parent Content scrolls, the submenu
visibly lags behind (or fully detaches from) its SubTrigger because the
scroll -> getBoundingClientRect -> reposition pipeline cannot keep pace
with fast wheel events.
Set updatePositionStrategy="always" so autoUpdate runs a continuous rAF
loop and the submenu tracks its trigger frame-by-frame. The prop is
placed after the {...props} spread so callers cannot accidentally revert
it.
Fixes #55856
Salvages #55858 (same one-prop fix, authored by David Metcalfe)
Co-authored-by: David Metcalfe <80915+DavidMetcalfe@users.noreply.github.com>
This commit is contained in:
@@ -487,6 +487,12 @@ function DropdownMenuSubContent({
|
||||
// `overflow` clip. Radix Popper still anchors it to the SubTrigger and
|
||||
// handles collision/flip. React events still bubble through the portal, so
|
||||
// the parent menu doesn't treat a press here as an outside click.
|
||||
//
|
||||
// `updatePositionStrategy="always"` makes Floating UI's autoUpdate use a
|
||||
// continuous rAF loop instead of the default "optimized" passive scroll
|
||||
// listeners. Without it, a portaled submenu visibly lags behind its trigger
|
||||
// while the parent Content scrolls: the scroll → getBoundingClientRect →
|
||||
// reposition pipeline cannot keep pace with fast wheel events.
|
||||
<DropdownMenuPrimitive.Portal container={container}>
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
// Fixed `max-h-80` rather than the Radix available-height variable:
|
||||
@@ -516,6 +522,10 @@ function DropdownMenuSubContent({
|
||||
// first (child effects run first), so Radix marks it `none`.
|
||||
style={{ ...(container ? { pointerEvents: 'auto' } : null), ...style }}
|
||||
{...props}
|
||||
// Placed after the spread so callers cannot override it: the rAF loop
|
||||
// is load-bearing for scroll-tracked submenus and must never revert to
|
||||
// the default passive-listener strategy.
|
||||
updatePositionStrategy="always"
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user