From a03652c88696433a485b67cb1b442a9789f9152a Mon Sep 17 00:00:00 2001 From: Mitchell Austin Date: Mon, 1 Sep 2025 12:31:00 -0700 Subject: [PATCH 1/2] Defer scrolling to wheel event target if it has overflow --- .../components/block-popover/use-popover-scroll.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/use-popover-scroll.js b/packages/block-editor/src/components/block-popover/use-popover-scroll.js index 5dfa74005a4081..d588884e13b10a 100644 --- a/packages/block-editor/src/components/block-popover/use-popover-scroll.js +++ b/packages/block-editor/src/components/block-popover/use-popover-scroll.js @@ -17,14 +17,24 @@ function usePopoverScroll( contentRef ) { const effect = useRefEffect( ( node ) => { function onWheel( event ) { - const { deltaX, deltaY } = event; + const { deltaX, deltaY, target } = event; const contentEl = contentRef.current; let scrollContainer = scrollContainerCache.get( contentEl ); if ( ! scrollContainer ) { scrollContainer = getScrollContainer( contentEl ); scrollContainerCache.set( contentEl, scrollContainer ); } - scrollContainer.scrollBy( deltaX, deltaY ); + let eventScrollContainer = scrollContainerCache.get( target ); + if ( ! eventScrollContainer ) { + eventScrollContainer = getScrollContainer( target ); + scrollContainerCache.set( target, eventScrollContainer ); + } + const { scrollHeight, offsetHeight } = eventScrollContainer; + // Scrolls “through” the popover only if the event target wasn’t within + // a scrollable container and thereby avoids scrolling both containers. + if ( scrollHeight === offsetHeight ) { + scrollContainer.scrollBy( deltaX, deltaY ); + } } // Tell the browser that we do not call event.preventDefault // See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners From ea0392745754068054e0cfcef90755e89c2c6760 Mon Sep 17 00:00:00 2001 From: Mitchell Austin Date: Wed, 3 Sep 2025 11:17:41 -0700 Subject: [PATCH 2/2] Remove event scroll container caching; test containment --- .../block-popover/use-popover-scroll.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/use-popover-scroll.js b/packages/block-editor/src/components/block-popover/use-popover-scroll.js index d588884e13b10a..2d3158e57d0ba7 100644 --- a/packages/block-editor/src/components/block-popover/use-popover-scroll.js +++ b/packages/block-editor/src/components/block-popover/use-popover-scroll.js @@ -24,15 +24,13 @@ function usePopoverScroll( contentRef ) { scrollContainer = getScrollContainer( contentEl ); scrollContainerCache.set( contentEl, scrollContainer ); } - let eventScrollContainer = scrollContainerCache.get( target ); - if ( ! eventScrollContainer ) { - eventScrollContainer = getScrollContainer( target ); - scrollContainerCache.set( target, eventScrollContainer ); - } - const { scrollHeight, offsetHeight } = eventScrollContainer; - // Scrolls “through” the popover only if the event target wasn’t within - // a scrollable container and thereby avoids scrolling both containers. - if ( scrollHeight === offsetHeight ) { + // Finds a scrollable ancestor of the event’s target. It's not cached because the + // it may not remain scrollable due to popover position changes. The cache is also + // less likely to be utilized because the target may be different every event. + const eventScrollContainer = getScrollContainer( target ); + // Scrolls “through” the popover only if another contained scrollable area isn’t + // in front of it. This is to avoid scrolling both containers simultaneously. + if ( ! node.contains( eventScrollContainer ) ) { scrollContainer.scrollBy( deltaX, deltaY ); } }