diff --git a/packages/block-editor/src/components/block-list/block-popover.js b/packages/block-editor/src/components/block-list/block-popover.js
index cb563c3319f21..8f04a3571aa73 100644
--- a/packages/block-editor/src/components/block-list/block-popover.js
+++ b/packages/block-editor/src/components/block-list/block-popover.js
@@ -128,11 +128,15 @@ function BlockPopover( {
className="block-editor-block-list__block-popover"
__unstableSticky={ showEmptyBlockSideInserter ? false : popoverIsSticky }
__unstableSlotName="block-toolbar"
+ __unstableBoundaryParent
// Allow subpixel positioning for the block movement animation.
__unstableAllowVerticalSubpixelPosition={ moverDirection !== 'horizontal' && node }
__unstableAllowHorizontalSubpixelPosition={ moverDirection === 'horizontal' && node }
onBlur={ () => setIsToolbarForced( false ) }
shouldAnchorIncludePadding
+ // Popover calculates the width once. Trigger a reset by remounting
+ // the component.
+ key={ shouldShowContextualToolbar }
>
{ ( shouldShowContextualToolbar || isToolbarForced ) && (
{
@@ -273,6 +274,12 @@ const Popover = ( {
contentRect.current = contentRef.current.getBoundingClientRect();
}
+ let boundaryElement;
+
+ if ( __unstableBoundaryParent ) {
+ boundaryElement = containerRef.current.closest( '.popover-slot' ).parentNode;
+ }
+
const {
popoverTop,
popoverLeft,
@@ -280,7 +287,14 @@ const Popover = ( {
yAxis,
contentHeight,
contentWidth,
- } = computePopoverPosition( anchor, contentRect.current, position, __unstableSticky, anchorRef );
+ } = computePopoverPosition(
+ anchor,
+ contentRect.current,
+ position,
+ __unstableSticky,
+ anchorRef,
+ boundaryElement
+ );
if ( typeof popoverTop === 'number' && typeof popoverLeft === 'number' ) {
if ( subpixels && __unstableAllowVerticalSubpixelPosition ) {
@@ -374,6 +388,7 @@ const Popover = ( {
__unstableSticky,
__unstableAllowVerticalSubpixelPosition,
__unstableAllowHorizontalSubpixelPosition,
+ __unstableBoundaryParent,
] );
useFocusContentOnMount( focusOnMount, contentRef );
@@ -511,6 +526,6 @@ const Popover = ( {
const PopoverContainer = Popover;
PopoverContainer.Slot = ( { name = SLOT_NAME } ) =>
- ;
+ ;
export default PopoverContainer;
diff --git a/packages/components/src/popover/utils.js b/packages/components/src/popover/utils.js
index 971ec4919d1c9..05ebfc7896be7 100644
--- a/packages/components/src/popover/utils.js
+++ b/packages/components/src/popover/utils.js
@@ -19,10 +19,11 @@ const HEIGHT_OFFSET = 10; // used by the arrow and a bit of empty space
* scroll container edge when part of the anchor
* leaves view.
* @param {string} chosenYAxis yAxis to be used.
+ * @param {Element} boundaryElement
*
* @return {Object} Popover xAxis position and constraints.
*/
-export function computePopoverXAxisPosition( anchorRect, contentSize, xAxis, corner, sticky, chosenYAxis ) {
+export function computePopoverXAxisPosition( anchorRect, contentSize, xAxis, corner, sticky, chosenYAxis, boundaryElement ) {
const { width } = contentSize;
const isRTL = document.documentElement.dir === 'rtl';
@@ -101,6 +102,11 @@ export function computePopoverXAxisPosition( anchorRect, contentSize, xAxis, cor
popoverLeft = rightAlignment.popoverLeft;
}
+ if ( boundaryElement ) {
+ const boundaryRect = boundaryElement.getBoundingClientRect();
+ popoverLeft = Math.min( popoverLeft, boundaryRect.right - width );
+ }
+
return {
xAxis: chosenXAxis,
popoverLeft,
@@ -222,14 +228,22 @@ export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, cor
* scroll container edge when part of the anchor
* leaves view.
* @param {Element} anchorRef The anchor element.
+ * @param {Element} boundaryElement
*
* @return {Object} Popover position and constraints.
*/
-export function computePopoverPosition( anchorRect, contentSize, position = 'top', sticky, anchorRef ) {
+export function computePopoverPosition(
+ anchorRect,
+ contentSize,
+ position = 'top',
+ sticky,
+ anchorRef,
+ boundaryElement
+) {
const [ yAxis, xAxis = 'center', corner ] = position.split( ' ' );
const yAxisPosition = computePopoverYAxisPosition( anchorRect, contentSize, yAxis, corner, sticky, anchorRef );
- const xAxisPosition = computePopoverXAxisPosition( anchorRect, contentSize, xAxis, corner, sticky, yAxisPosition.yAxis );
+ const xAxisPosition = computePopoverXAxisPosition( anchorRect, contentSize, xAxis, corner, sticky, yAxisPosition.yAxis, boundaryElement );
return {
...xAxisPosition,