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() {
+