From 5454ccb75a942810517b67de965bcbf760053b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20van=C2=A0Durpe?= Date: Wed, 22 Jan 2020 16:58:37 +0100 Subject: [PATCH] Block popover: allow scrolling over (#19769) * Block popover: allow scrolling over * Clean up * Fix overlapping inserter popover * Better comment --- packages/base-styles/_z-index.scss | 3 ++ .../components/block-list/insertion-point.js | 2 +- .../src/components/block-list/style.scss | 13 ++++++ packages/components/src/popover/index.js | 25 +++++++++- packages/components/src/popover/utils.js | 46 ++++++++++--------- .../edit-post/src/components/layout/index.js | 1 - .../src/components/visual-editor/index.js | 2 + 7 files changed, 67 insertions(+), 25 deletions(-) diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index f9c23e29b6062..5936812f94812 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -85,6 +85,9 @@ $z-layers: ( // Above the block list, under the header. ".block-editor-block-list__block-popover": 29, + // Under the block popover (block toolbar). + ".block-editor-block-list__insertion-point-popover": 28, + // Show snackbars above everything (similar to popovers) ".components-snackbar-list": 100000, diff --git a/packages/block-editor/src/components/block-list/insertion-point.js b/packages/block-editor/src/components/block-list/insertion-point.js index 80fdee37f18ff..336887375b527 100644 --- a/packages/block-editor/src/components/block-list/insertion-point.js +++ b/packages/block-editor/src/components/block-list/insertion-point.js @@ -122,7 +122,7 @@ export default function InsertionPoint( { anchorRef={ inserterElement } position="top right left" focusOnMount={ false } - className="block-editor-block-list__block-popover" + className="block-editor-block-list__insertion-point-popover" __unstableSlotName="block-toolbar" >
diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index ff63879a08f61..8124ca1beb4cd 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -537,8 +537,21 @@ } } +.block-editor-block-list__insertion-point-popover { + z-index: z-index(".block-editor-block-list__insertion-point-popover"); + position: absolute; + + .components-popover__content { + background: none; + border: none; + box-shadow: none; + overflow-y: visible; + } +} + .components-popover.block-editor-block-list__block-popover { z-index: z-index(".block-editor-block-list__block-popover"); + position: absolute; .components-popover__content { margin: 0 !important; diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index ca1b953c27ee1..82cb3874db2fb 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -257,7 +257,8 @@ const Popover = ( { if ( ! containerRef.current || ! contentRef.current ) { return; } - const anchor = computeAnchorRect( + + let anchor = computeAnchorRect( anchorRefFallback, anchorRect, getAnchorRect, @@ -273,6 +274,26 @@ const Popover = ( { contentRect.current = contentRef.current.getBoundingClientRect(); } + const { offsetParent, ownerDocument } = containerRef.current; + let relativeOffsetTop = 0; + + // If there is a positioned ancestor element that is not the body, + // subtract the position from the anchor rect. If the position of + // the popover is fixed, the offset parent is null or the body + // element, in which case the position is relative to the viewport. + // See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent + if ( offsetParent && offsetParent !== ownerDocument.body ) { + const offsetParentRect = offsetParent.getBoundingClientRect(); + + relativeOffsetTop = offsetParentRect.top; + anchor = new window.DOMRect( + anchor.left - offsetParentRect.left, + anchor.top - offsetParentRect.top, + anchor.width, + anchor.height + ); + } + const { popoverTop, popoverLeft, @@ -280,7 +301,7 @@ const Popover = ( { yAxis, contentHeight, contentWidth, - } = computePopoverPosition( anchor, contentRect.current, position, __unstableSticky, anchorRef ); + } = computePopoverPosition( anchor, contentRect.current, position, __unstableSticky, anchorRef, relativeOffsetTop ); if ( typeof popoverTop === 'number' && typeof popoverLeft === 'number' ) { if ( subpixels && __unstableAllowVerticalSubpixelPosition ) { diff --git a/packages/components/src/popover/utils.js b/packages/components/src/popover/utils.js index 971ec4919d1c9..f729247c98d7f 100644 --- a/packages/components/src/popover/utils.js +++ b/packages/components/src/popover/utils.js @@ -111,18 +111,20 @@ export function computePopoverXAxisPosition( anchorRect, contentSize, xAxis, cor /** * Utility used to compute the popover position over the yAxis * - * @param {Object} anchorRect Anchor Rect. - * @param {Object} contentSize Content Size. - * @param {string} yAxis Desired yAxis. - * @param {string} corner Desired corner. - * @param {boolean} sticky Whether or not to stick the popover to the - * scroll container edge when part of the anchor - * leaves view. - * @param {Element} anchorRef The anchor element. + * @param {Object} anchorRect Anchor Rect. + * @param {Object} contentSize Content Size. + * @param {string} yAxis Desired yAxis. + * @param {string} corner Desired corner. + * @param {boolean} sticky Whether or not to stick the popover to the + * scroll container edge when part of the + * anchor leaves view. + * @param {Element} anchorRef The anchor element. + * @param {Element} relativeOffsetTop If applicable, top offset of the relative + * positioned parent container. * * @return {Object} Popover xAxis position and constraints. */ -export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, corner, sticky, anchorRef ) { +export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, corner, sticky, anchorRef, relativeOffsetTop ) { const { height } = contentSize; if ( sticky ) { @@ -146,7 +148,7 @@ export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, cor if ( topRect.top - height <= scrollRect.top ) { return { yAxis, - popoverTop: Math.min( bottomRect.bottom, scrollRect.top + height ), + popoverTop: Math.min( bottomRect.bottom - relativeOffsetTop, scrollRect.top + height - relativeOffsetTop ), }; } } @@ -212,23 +214,25 @@ export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, cor } /** - * Utility used to compute the popover position and the content max width/height for a popover - * given its anchor rect and its content size. + * Utility used to compute the popover position and the content max width/height + * for a popover given its anchor rect and its content size. * - * @param {Object} anchorRect Anchor Rect. - * @param {Object} contentSize Content Size. - * @param {string} position Position. - * @param {boolean} sticky Whether or not to stick the popover to the - * scroll container edge when part of the anchor - * leaves view. - * @param {Element} anchorRef The anchor element. + * @param {Object} anchorRect Anchor Rect. + * @param {Object} contentSize Content Size. + * @param {string} position Position. + * @param {boolean} sticky Whether or not to stick the popover to the + * scroll container edge when part of the + * anchor leaves view. + * @param {Element} anchorRef The anchor element. + * @param {number} relativeOffsetTop If applicable, top offset of the relative + * positioned parent container. * * @return {Object} Popover position and constraints. */ -export function computePopoverPosition( anchorRect, contentSize, position = 'top', sticky, anchorRef ) { +export function computePopoverPosition( anchorRect, contentSize, position = 'top', sticky, anchorRef, relativeOffsetTop ) { const [ yAxis, xAxis = 'center', corner ] = position.split( ' ' ); - const yAxisPosition = computePopoverYAxisPosition( anchorRect, contentSize, yAxis, corner, sticky, anchorRef ); + const yAxisPosition = computePopoverYAxisPosition( anchorRect, contentSize, yAxis, corner, sticky, anchorRef, relativeOffsetTop ); const xAxisPosition = computePopoverXAxisPosition( anchorRect, contentSize, xAxis, corner, sticky, yAxisPosition.yAxis ); return { diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 7dbb356815d0e..09a3f485d13e0 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -108,7 +108,6 @@ function Layout() { content={ <> - { ( mode === 'text' || ! isRichEditingEnabled ) && } { isRichEditingEnabled && mode === 'visual' && }
diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js index 37d3749f0f498..52f50c5d9e36b 100644 --- a/packages/edit-post/src/components/visual-editor/index.js +++ b/packages/edit-post/src/components/visual-editor/index.js @@ -16,6 +16,7 @@ import { __experimentalBlockSettingsMenuFirstItem, __experimentalBlockSettingsMenuPluginsExtension, } from '@wordpress/block-editor'; +import { Popover } from '@wordpress/components'; /** * Internal dependencies @@ -28,6 +29,7 @@ function VisualEditor() { +