From 484c96035f521ff519afe7986c2199536a1e1485 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 22 Oct 2024 09:24:49 +1100 Subject: [PATCH] Block toolbar: account for scrollable blocks that affect the position of the block toolbar (#66188) The rect bounds of blocvk child elements, specifically the x and y values, change when the element is scrolled. This change attempts to correct the overflow so the scrollable children do not influence the x,y values of the block toolbar popover. Co-authored-by: ramonjd Co-authored-by: aaronrobertshaw Co-authored-by: andrewserong Co-authored-by: t-hamano Co-authored-by: kevin940726 --- packages/block-editor/src/utils/dom.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/utils/dom.js b/packages/block-editor/src/utils/dom.js index 9c2e813ef742b6..0603e9bbb1db96 100644 --- a/packages/block-editor/src/utils/dom.js +++ b/packages/block-editor/src/utils/dom.js @@ -118,6 +118,22 @@ function isElementVisible( element ) { return true; } +/** + * Checks if the element is scrollable. + * + * @param {Element} element Element. + * @return {boolean} True if the element is scrollable. + */ +function isScrollable( element ) { + const style = window.getComputedStyle( element ); + return ( + style.overflowX === 'auto' || + style.overflowX === 'scroll' || + style.overflowY === 'auto' || + style.overflowY === 'scroll' + ); +} + /** * Returns the rect of the element including all visible nested elements. * @@ -136,19 +152,23 @@ function isElementVisible( element ) { */ export function getVisibleElementBounds( element ) { const viewport = element.ownerDocument.defaultView; + if ( ! viewport ) { return new window.DOMRectReadOnly(); } let bounds = element.getBoundingClientRect(); - const stack = [ element ]; let currentElement; while ( ( currentElement = stack.pop() ) ) { for ( const child of currentElement.children ) { if ( isElementVisible( child ) ) { - const childBounds = child.getBoundingClientRect(); + let childBounds = child.getBoundingClientRect(); + // If the parent is scrollable, use parent's scrollable bounds. + if ( isScrollable( currentElement ) ) { + childBounds = currentElement.getBoundingClientRect(); + } bounds = rectUnion( bounds, childBounds ); stack.push( child ); }