Skip to content

Commit

Permalink
Update the block popover position as we scroll the container (#41402)
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed Jun 3, 2022
1 parent f5f2a74 commit 00a17c0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default function BlockPopover( {
// Observe movement for block animations (especially horizontal).
__unstableObserveElement={ selectedElement }
__unstableForcePosition
__unstableShift
{ ...props }
className={ classnames(
'block-editor-block-popover',
Expand Down
64 changes: 39 additions & 25 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const Popover = (
__unstableSlotName = SLOT_NAME,
__unstableObserveElement,
__unstableForcePosition,
__unstableShift = false,
...contentProps
},
ref
Expand All @@ -134,26 +135,29 @@ const Popover = (
? positionToPlacement( position )
: placement;

/**
* Offsets the the position of the popover when the anchor is inside an iframe.
*/
const frameOffset = useMemo( () => {
let ownerDocument = document;
const ownerDocument = useMemo( () => {
if ( anchorRef?.top ) {
ownerDocument = anchorRef?.top.ownerDocument;
return anchorRef?.top.ownerDocument;
} else if ( anchorRef?.startContainer ) {
ownerDocument = anchorRef.startContainer.ownerDocument;
return anchorRef.startContainer.ownerDocument;
} else if ( anchorRef?.current ) {
ownerDocument = anchorRef.current.ownerDocument;
return anchorRef.current.ownerDocument;
} else if ( anchorRef ) {
// This one should be deprecated.
ownerDocument = anchorRef.ownerDocument;
return anchorRef.ownerDocument;
} else if ( anchorRect && anchorRect?.ownerDocument ) {
ownerDocument = anchorRect.ownerDocument;
return anchorRect.ownerDocument;
} else if ( getAnchorRect ) {
ownerDocument = getAnchorRect()?.ownerDocument ?? document;
return getAnchorRect()?.ownerDocument ?? document;
}

return document;
}, [ anchorRef, anchorRect, getAnchorRect ] );

/**
* Offsets the the position of the popover when the anchor is inside an iframe.
*/
const frameOffset = useMemo( () => {
const { defaultView } = ownerDocument;
const { frameElement } = defaultView;

Expand All @@ -171,7 +175,7 @@ const Popover = (
};
},
};
}, [ anchorRef, anchorRect, getAnchorRect ] );
}, [ ownerDocument ] );

const middlewares = [
frameOffset,
Expand All @@ -190,12 +194,13 @@ const Popover = (
} );
},
} ),
,
shift( {
crossAxis: true,
limiter: limitShift(),
padding: 1, // Necessary to avoid flickering at the edge of the viewport.
} ),
__unstableShift
? shift( {
crossAxis: true,
limiter: limitShift(),
padding: 1, // Necessary to avoid flickering at the edge of the viewport.
} )
: undefined,
hasArrow ? arrow( { element: arrowRef } ) : undefined,
].filter( ( m ) => !! m );
const anchorRefFallback = useRef( null );
Expand Down Expand Up @@ -271,13 +276,12 @@ const Popover = (
usedRef = {
getBoundingClientRect() {
const rect = getAnchorRect();
return {
...rect,
x: rect.x ?? rect.left,
y: rect.y ?? rect.top,
height: rect.height ?? rect.bottom - rect.top,
width: rect.width ?? rect.right - rect.left,
};
return new window.DOMRect(
rect.x ?? rect.left,
rect.y ?? rect.top,
rect.width ?? rect.right - rect.left,
rect.height ?? rect.bottom - rect.top
);
},
};
} else if ( anchorRefFallback.current ) {
Expand Down Expand Up @@ -310,6 +314,16 @@ const Popover = (
};
}, [ __unstableObserveElement ] );

// If we're using getAnchorRect, we need to update the position as we scroll the iframe.
useLayoutEffect( () => {
if ( ownerDocument === document ) {
return;
}

ownerDocument.addEventListener( 'scroll', update );
return () => ownerDocument.removeEventListener( 'scroll', update );
}, [ ownerDocument ] );

/** @type {false | string} */
const animateClassName =
!! animate &&
Expand Down

0 comments on commit 00a17c0

Please sign in to comment.