Block Editor Focus Restoration After Closing Nested Block Inserters in WordPress 6.2+
0 reputation · 09 Apr 2020, 22:30 UTC
0 reputation · 09 Apr 2020, 22:30 UTC
The goal is to achieve predictable keyboard focus restoration whenever a user closes a nested block inserter in the WordPress Block Editor, so that editing flow remains uninterrupted for screen‑reader and keyboard‑only users.
Although WordPress 6.2 added ARIA labels, a focus trap for the inserter, and improved toolbar navigation, the mechanism that returns focus after the inserter is dismissed varies: sometimes focus goes back to the previously edited block, other times it jumps to the page body or the toolbar. This inconsistency is influenced by active themes or plugins that may alter the editor’s DOM, and the project is debating whether to introduce an explicit focus‑return API or to rely on the browser’s native focus management.
Should WordPress adopt an explicit focus‑return API for the block inserter? How can theme and plugin developers avoid interfering with focus restoration? What testing strategy best validates consistent focus behavior across assistive technologies?
35275 reputation · 10 Apr 2020, 05:27 UTC
Should WordPress adopt an explicit focus‑return API? Yes, but only as a fallback for complex nested inserters. Core currently relies on the browser’s native focus management, which works for simple cases but fails when the inserter’s portal or the block toolbar is removed from the DOM during the close animation. An explicit API would let the core, themes, and plugins coordinate a deterministic return target without depending on the element’s presence.
FocusLock around the inserter panel and ARIA labels on the trigger button.focus() on the trigger button if it still exists. If the button is unmounted or moved, the browser falls back to document.body or the nearest focusable ancestor.visibility:hidden or opacity:0 instead of unmounting.focus listeners that call preventDefault() or move focus during the inserter’s open state.__unstableIsInserterOpened selector returns false.
useEffect(() => { if (!isInserterOpened) { /* safe DOM changes */ } }, [isInserterOpened]);wp.data selectors (getInserterItems, isInserterOpened) instead of querying the DOM directly.Combine automated and manual tests to cover screen‑reader and keyboard‑only users.
@testing-library/react and userEvent.tab() to simulate opening and closing the inserter.
document.activeElement after dismiss matches the element that had focus before the inserter opened.test:e2e suite against multiple themes (Twenty Twenty‑Four, a block‑heavy theme) and plugins that add custom block variations.document.activeElement to the CI pipeline and fail if it changes unexpectedly.Does your project currently unmount the block toolbar or the inserter trigger button when the inserter is opened, or use preventDefault() in a global focus handler?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.