diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js
index e0884300f1b37..cfafa6c031bbd 100644
--- a/packages/block-editor/src/components/block-lock/modal.js
+++ b/packages/block-editor/src/components/block-lock/modal.js
@@ -41,7 +41,7 @@ function getTemplateLockValue( lock ) {
return false;
}
-export default function BlockLockModal( { clientId, onClose, onFocusReturn } ) {
+export default function BlockLockModal( { clientId, onClose } ) {
const [ lock, setLock ] = useState( { move: false, remove: false } );
const { canEdit, canMove, canRemove } = useBlockLock( clientId );
const { allowsEditLocking, templateLock, hasTemplateLock } = useSelect(
@@ -89,7 +89,6 @@ export default function BlockLockModal( { clientId, onClose, onFocusReturn } ) {
) }
overlayClassName="block-editor-block-lock-modal"
onRequestClose={ onClose }
- onFocusReturn={ onFocusReturn }
>
{ __(
diff --git a/packages/block-editor/src/components/block-lock/toolbar.js b/packages/block-editor/src/components/block-lock/toolbar.js
index 41fccbdbe5611..2dcbb18a20223 100644
--- a/packages/block-editor/src/components/block-lock/toolbar.js
+++ b/packages/block-editor/src/components/block-lock/toolbar.js
@@ -4,7 +4,7 @@
import { __ } from '@wordpress/i18n';
import { ToolbarButton, ToolbarGroup } from '@wordpress/components';
import { focus } from '@wordpress/dom';
-import { useReducer, useRef } from '@wordpress/element';
+import { useReducer, useRef, useEffect } from '@wordpress/element';
import { lock } from '@wordpress/icons';
/**
@@ -22,12 +22,33 @@ export default function BlockLockToolbar( { clientId, wrapperRef } ) {
);
const lockButtonRef = useRef( null );
+ const isFirstRender = useRef( true );
- if ( ! canLock ) {
- return null;
- }
+ const shouldHideBlockLockUI =
+ ! canLock || ( canEdit && canMove && canRemove );
+
+ useEffect( () => {
+ if ( isFirstRender.current ) {
+ isFirstRender.current = false;
+ return;
+ }
- if ( canEdit && canMove && canRemove ) {
+ if ( ! isModalOpen && shouldHideBlockLockUI ) {
+ focus.focusable
+ .find( wrapperRef.current, {
+ sequential: false,
+ } )
+ .find(
+ ( element ) =>
+ element.tagName === 'BUTTON' &&
+ element !== lockButtonRef.current
+ )
+ ?.focus();
+ }
+ // wrapperRef is a reference object and should be stable
+ }, [ isModalOpen, shouldHideBlockLockUI, wrapperRef ] );
+
+ if ( shouldHideBlockLockUI ) {
return null;
}
@@ -42,39 +63,7 @@ export default function BlockLockToolbar( { clientId, wrapperRef } ) {
/>
{ isModalOpen && (
- {
- // Try to focus the element that should have received
- // focus by default.
- if ( defaultFocusReturnElement ) {
- defaultFocusReturnElement.focus();
- }
-
- // Check if the element that should have received focus is effectively
- // the current active element. This check is useful when the element
- // that should have received focus is not being rendered in the DOM.
- if (
- defaultFocusReturnElement.ownerDocument
- .activeElement !== defaultFocusReturnElement &&
- wrapperRef.current
- ) {
- // As a fallback, focus the first focusable button
- // found in the toolbar
- focus.focusable
- .find( wrapperRef.current, {
- sequential: false,
- } )
- .find(
- ( element ) =>
- element.tagName === 'BUTTON' &&
- element !== lockButtonRef.current
- )
- ?.focus();
- }
- } }
- />
+
) }
>
);
diff --git a/packages/components/src/modal/index.tsx b/packages/components/src/modal/index.tsx
index 75d5bd1043ee0..d9c7b602b8392 100644
--- a/packages/components/src/modal/index.tsx
+++ b/packages/components/src/modal/index.tsx
@@ -67,7 +67,6 @@ function UnforwardedModal(
onKeyDown,
isFullScreen = false,
__experimentalHideHeader = false,
- onFocusReturn,
} = props;
const ref = useRef< HTMLDivElement >();
@@ -77,7 +76,7 @@ function UnforwardedModal(
: aria.labelledby;
const focusOnMountRef = useFocusOnMount( focusOnMount );
const constrainedTabbingRef = useConstrainedTabbing();
- const focusReturnRef = useFocusReturn( onFocusReturn );
+ const focusReturnRef = useFocusReturn();
const focusOutsideProps = useFocusOutside( onRequestClose );
const contentRef = useRef< HTMLDivElement >( null );
const childrenContainerRef = useRef< HTMLDivElement >( null );
diff --git a/packages/components/src/modal/types.ts b/packages/components/src/modal/types.ts
index 46497471ab0e3..6169e42a8a2d4 100644
--- a/packages/components/src/modal/types.ts
+++ b/packages/components/src/modal/types.ts
@@ -143,9 +143,4 @@ export type ModalProps = {
* @default false
*/
__experimentalHideHeader?: boolean;
- /**
- * Callback called when the modal is dismissed. Used to implement custom
- * focus restoration behavior.
- */
- onFocusReturn?: ( defaultFocusReturnElement: Element | null ) => void;
};
diff --git a/packages/compose/src/hooks/use-focus-return/index.js b/packages/compose/src/hooks/use-focus-return/index.js
index e588f653e90b8..66751b7028d32 100644
--- a/packages/compose/src/hooks/use-focus-return/index.js
+++ b/packages/compose/src/hooks/use-focus-return/index.js
@@ -9,7 +9,7 @@ import { useRef, useEffect, useCallback } from '@wordpress/element';
* previously focused element when closed.
* The current hook implements the returning behavior.
*
- * @param {( defaultElementToFocus: Element | null ) => void} [onFocusReturn] Overrides the default return behavior.
+ * @param {() => void} [onFocusReturn] Overrides the default return behavior.
* @return {import('react').RefCallback} Element Ref.
*
* @example
@@ -62,14 +62,12 @@ function useFocusReturn( onFocusReturn ) {
// decides to allow the default behavior to occur under some
// conditions.
if ( onFocusReturnRef.current ) {
- onFocusReturnRef.current( focusedBeforeMount.current );
+ onFocusReturnRef.current();
} else {
/** @type {null | HTMLElement} */ (
focusedBeforeMount.current
)?.focus();
}
- } else if ( onFocusReturnRef.current ) {
- onFocusReturnRef.current( focusedBeforeMount.current );
}
}, [] );
}