diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 370959d1b145c..597f61eb94910 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -6,8 +6,9 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { useMergeRefs } from '@wordpress/compose'; import { Popover } from '@wordpress/components'; -import { useMemo } from '@wordpress/element'; +import { forwardRef, useMemo } from '@wordpress/element'; /** * Internal dependencies @@ -15,19 +16,25 @@ import { useMemo } from '@wordpress/element'; import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; -export default function BlockPopover( { - clientId, - bottomClientId, - children, - __unstableRefreshSize, - __unstableCoverTarget = false, - __unstablePopoverSlot, - __unstableContentRef, - ...props -} ) { +function BlockPopover( + { + clientId, + bottomClientId, + children, + __unstableRefreshSize, + __unstableCoverTarget = false, + __unstablePopoverSlot, + __unstableContentRef, + ...props + }, + ref +) { const selectedElement = useBlockElement( clientId ); const lastSelectedElement = useBlockElement( bottomClientId ?? clientId ); - const popoverScrollRef = usePopoverScroll( __unstableContentRef ); + const mergedRefs = useMergeRefs( [ + ref, + usePopoverScroll( __unstableContentRef ), + ] ); const style = useMemo( () => { if ( ! selectedElement || lastSelectedElement !== selectedElement ) { return {}; @@ -51,7 +58,7 @@ export default function BlockPopover( { return ( ); } + +export default forwardRef( BlockPopover ); diff --git a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js index 7c5eb35c6052f..f7684115632b5 100644 --- a/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js +++ b/packages/block-editor/src/components/block-tools/use-block-toolbar-popover-props.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { useRefEffect } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; import { useEffect, useState } from '@wordpress/element'; @@ -10,14 +11,13 @@ import { useEffect, useState } from '@wordpress/element'; import { store as blockEditorStore } from '../../store'; import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; -const TOOLBAR_HEIGHT = 72; const DEFAULT_PROPS = { __unstableForcePosition: true, __unstableShift: true }; const RESTRICTED_HEIGHT_PROPS = { __unstableForcePosition: false, __unstableShift: false, }; -function getProps( contentElement, selectedBlockElement ) { +function getProps( contentElement, selectedBlockElement, toolbarHeight ) { if ( ! contentElement || ! selectedBlockElement ) { return DEFAULT_PROPS; } @@ -25,7 +25,7 @@ function getProps( contentElement, selectedBlockElement ) { const blockRect = selectedBlockElement.getBoundingClientRect(); const contentRect = contentElement.getBoundingClientRect(); - if ( blockRect.top - contentRect.top > TOOLBAR_HEIGHT ) { + if ( blockRect.top - contentRect.top > toolbarHeight ) { return DEFAULT_PROPS; } @@ -48,18 +48,18 @@ export default function useBlockToolbarPopoverProps( { clientId, } ) { const selectedBlockElement = useBlockElement( clientId ); + const [ toolbarHeight, setToolbarHeight ] = useState( 0 ); const [ props, setProps ] = useState( - getProps( contentElement, selectedBlockElement ) + getProps( contentElement, selectedBlockElement, toolbarHeight ) ); const blockIndex = useSelect( ( select ) => select( blockEditorStore ).getBlockIndex( clientId ), [ clientId ] ); - // Update the toolbar position if the block moves. - useEffect( () => { - setProps( getProps( contentElement, selectedBlockElement ) ); - }, [ blockIndex ] ); + const popoverRef = useRefEffect( ( popoverNode ) => { + setToolbarHeight( popoverNode.offsetHeight ); + }, [] ); // Update the toolbar position if the window resizes, or the // selected element changes. @@ -69,7 +69,9 @@ export default function useBlockToolbarPopoverProps( { } const updateProps = () => - setProps( getProps( contentElement, selectedBlockElement ) ); + setProps( + getProps( contentElement, selectedBlockElement, toolbarHeight ) + ); updateProps(); const view = contentElement?.ownerDocument?.defaultView; @@ -78,7 +80,10 @@ export default function useBlockToolbarPopoverProps( { return () => { view?.removeEventHandler?.( 'resize', updateProps ); }; - }, [ contentElement, selectedBlockElement ] ); + }, [ contentElement, selectedBlockElement, blockIndex, toolbarHeight ] ); - return props; + return { + ...props, + ref: popoverRef, + }; }